php calculate formula in string [duplicate] - php

This question already has an answer here:
How to evaluate formula passed as string in PHP?
(1 answer)
Closed 9 years ago.
So I have formula as string
$comm = "(a x 5% - 2%)";
I want it to be $comm = $a * 5/100 * (1-2/100);
How can I do this in php?

Take a look at
http://www.phpclasses.org/package/2695-PHP-Safely-evaluate-mathematical-expressions.html
Which can evaluate Math Code
// instantiate a new EvalMath
$m = new EvalMath;
$m->suppress_errors = true;
// set the value of x
$m->evaluate('x = 3');
var_dump($m->evaluate('y = (x > 5)'));
Found at:
Process mathematical equations in php

To do this the right way, reliably and safely, from scratch, you will need to perform:
Lexical analysis, this involves pattern matching the input with tokens:
(a x 5% - 2%)
would become something like the following chain of tokens:
openparen variable multiply integer percent minus integer percent closeparen
Syntax analysis, this involves taking those tokens and defining the relationships between them, something like this, matching up the patterns of tokens:
statement = operand operator statement
Then you will need to parse the resulting syntax tree so that you can run it and produce the answer.
It won't ever look as simple as $comm = $a * 5/100 - 2/100; but it will result in the same conclusion.
Someone somewhere has already likely had a go at this problem, here's two I found after a brief Google search:
PHP Maths Expression Parser,
And another.
These SO questions are similar as well Smart design of a math parser?, Process mathematical equations in php

It just trying, but maybe good start.
$somm = 0;
$a = 30;
$str = "(a x 5% - 2%)";
$pt1 = "/x/i";
$str = preg_replace($pt1, "*", $str);
$pt2 = "/([a-z])+/i";
$str = preg_replace($pt2, "\$$0", $str);
$pt3 = "/([0-9])+%/";
$str = preg_replace($pt3, "($0/100)", $str);
$pt4 = "/%/";
$str = preg_replace($pt4, "", $str);
$e = "\$comm = $str;";
eval($e);
echo $e . "<br>";
echo $comm;

Solved!!
<?php
function evalmath($equation)
{
$result = 0;
// sanitize imput
$equation = preg_replace("/[^a-z0-9+\-.*\/()%]/","",$equation);
// convert alphabet to $variabel
$equation = preg_replace("/([a-z])+/i", "\$$0", $equation);
// convert percentages to decimal
$equation = preg_replace("/([+-])([0-9]{1})(%)/","*(1\$1.0\$2)",$equation);
$equation = preg_replace("/([+-])([0-9]+)(%)/","*(1\$1.\$2)",$equation);
$equation = preg_replace("/([0-9]{1})(%)/",".0\$1",$equation);
$equation = preg_replace("/([0-9]+)(%)/",".\$1",$equation);
/*if ( $equation != "" ){
$result = #eval("return " . $equation . ";" );
}
if ($result == null) {
throw new Exception("Unable to calculate equation");
}
return $result;*/
return $equation;
}
$total = 18000;
$equation = evalmath('total-(230000*5%-2%+3000*2*1)');
if ( $equation != "" ){
$result = #eval("return " . $equation . ";" );
}
if ($result == null) {
throw new Exception("Unable to calculate equation");
}
echo $result;
?>

Related

How to calculate (+ or - or * or /) using php variable? [duplicate]

This question already has answers here:
Shunting Yard implementation in PHP needed, interpret and parse a string perform a mathematical comparison and return a boolean result
(4 answers)
Closed 7 years ago.
Why this 2 code not echo same result ?
On first code echo *57, But i want to echo 35 like on second code.
How can i do that ?
<?PHP
$fomular = "*5";
$x = "7";
$res = $fomular."".$x;
echo $res;
?>
<?PHP
echo 5*7;
?>
There are a couple of issues.
In your example
...
$res = $fomular."".$x;
...
Is the same as saying
...
$res = "*5".""."3";
...
So that explains the "*53" been echoed/
...
$res = $fomular + $x;
// or
$res = $x + $fomular;
...
Will return 12 as it will not evaluate the "*" but rather add the numbers.
You could use eval( ... ) but it is evil and would really advise against it.
...
echo eval( "5*" . "7" . ";");
...
So your best bet, if you really want to echo the result, would be to write your own function to parse the 2 strings and do the operation.
That is because when you use .(dot) operator it appends the two variables.
You have to use code like below to get the desired output
$formular = 5;
$x=7;
$res=$formular * $x;
echo $res;
$formular = 5;
$x = 7;
$res = $formular * $x;
echo $res;
. (dot) in php is a string concatenating operator! if you try to use it with any type of variables, it converts they to string and put together. Sample: $x = 5 . 7 -> $x = '57'; but, if you use any kind of mathematicals operators (*, /, +, -), php will convert both operands to numeric form (float or int), then execute your formula and give a result $x = 5 * 7; -> $x = 35;
In short: use only mathematicals operators for executing formulas, not a dot. (sory for my bad english)

Translate phrase with more than 1 singular/plural value

I have the following phrase and want to translate it.
$lifeTime = 'Expires in '.$days.($days == 1 ? ' day ':' days ' ).$h.(($h == 1 ? ' hour ':' hours ' ));
My question is: will I need to split the phrase, translate separated and concatenate them ? Is there a way to __n() function accept multiple "instances" of singular/plural with their respective counts on a single phrase ?
A bit confusing. A example to make it clear:
__('I have %s eggs and %s milk boxes', $eggs, $milk)
This will not have singular and plural form. Can I make it translate the entire phrase without having to split it in two __n() function calls ?
If you know beforehand what words might come in your strings you could do as follows:
// the preperation/setup
$translations = Array();
$translations['hours']['search'] = "%hour";
$translations['hours']['inflections'] = Array("hour", "hours");
$translations['milk']['search'] = "%milk";
$translations['milk']['inflections'] = Array("milk bottle", "bottles of milk");
// add what else you might need
function replaceWithPlurals($heystack, $translations) {
foreach ($translations as $key => $vals) {
$heystack = str_replace($vals['search'], $vals['cnt']." ".$vals['inflections'][usePlural($vals['cnt'])], $heystack);
}
return $heystack;
}
function usePlural($cnt) {
if($cnt==1) return 0;
else return 1;
}
// dynamic vars
$heystack = "I drank %milk in %hour";
$hours = 1;
$milk = 2;
$translations['hours']['cnt'] = $hours;
$translations['milk']['cnt'] = $milk;
// the actual usage
echo replaceWithPlurals($heystack, $translations);
overall that's quite a lot of preperation if you would only need that for 4 specific occations. But if you regular use it I hope that will help.

how can i divide numerator by any similar to 0.0110932 in PHP?

I'm getting error like PHP
Warning: Division by zero error.
I'm still and want to calculate some problems. If you can tell me, how can calculate antilog / log inverse with examples, I'll be more satisfied.
<?
if(isset($_POST['submit']))
{
$P=$_POST['P']; // P=100000
$rate=$_POST['rate']; // rate = 10.5
$R=($rate/100);
$N=$_POST['N']; // N = 78
echo $P ."<br>" ;
echo $R ."<br>" ;
echo $N ."<br>" ;
$NEW=($R/12); // NEW = .00875
$aa = (1+($NEW)); // aa = 1.00875
$ab = bcpow('$aa', '$N',16); // ab = 1.9729529246182467
$ac = ($ab-1); // ac = 0.9729529246182467
$ad = bcdiv('$ab', '$ac', 3); // Div by Zero Error
$M = ($P*$NEW) *($ad);
echo "The Installment is : " . $M . "<br>";
}
?>
The line with the problem:
$ad = bcdiv('$ab', '$ac', 3); // Div by Zero Error
The problem here is because $ab and $ac are in quotes. They shouldn't be.
Having them in quotes means that PHP sees $ab as being a string consisting of the characters $, a and b, instead of the numeric value of the $ab variable.
Remove the quotes, and it should start working.
The same applies to the bcpow() line.
bcpow('$aa', '$N',16); are you sure these variables get parsed? They are treated as a string in single quotes, and since there is no number they might be just bogus. (typing $aa^$n on a calculator will fail).
You can use bcpow("'".$aa."'", "'".$N."'",16); or try using double quotes.
I didn't understood your code as well, but here is the code that calculate Antilog / log of a value
<?php
$log = 11;
$e = 2.718281828;
$dn = 1;
// Calculate Antilog of $log = 11
$ans = pow($e, $log);
$antilog = round($ans*10000)/10000;
echo "<br /> Antilog : ".$antilog;
// Calculate Log of $log = 11
$ans = log($log)/$dn;
$log = round($ans*10000)/10000;
echo "<br /> Log : ".$log;
// Calculate Antilog / Log of $log = 11
echo "<br /> Antilog / Log : ".($antilog / $log);
?>
Result:
Antilog : 59874.1416
Log : 2.3979
Antilog / Log : 24969.407231327
Hope this help you, if else please provide more details (comments) on your code.
To narrow down where your issue is coming from:
string bcdiv ( string $left_operand , string $right_operand [, int $scale ] )
bcdiv will return Division by zero only if the right operand is 0, so you can backtrace this by assuming $ac is your culprint. Try echoing $ac before the bcdiv function call to ensure it is not empty.
I'm willing to bet that this line $ac = ($ab-1); // ac = 0.9729529246182467
$ac is going negative.
You should also remove your single quotes, don't take the manual so literal. You can still pass in an int or double and the function will convert it for you. even if you cast the variable as a double.
//WITHOUT QUOTES
$ab = '1.9729529246182467';
$ac = ($ab-1);
echo bcdiv($ab, $ac, 3);
//output (2.027)
//WITH QUOTES
$ab = '1.9729529246182467';
$ac = ($ab-1);
echo bcdiv($ab, '$ac', 3);
//output Warning (2): bcdiv() [function.bcdiv]: Division by zero

Comparing two Arabic-language string values in PHP?

I'm having problems trying to compare two Arabic-language strings in a PHP script to see if they match. I've tried setting the internal encoding to UTF-8 with mb_internal_encoding, I've tried a simple if ($x == $y) expression, I've tried strcmp()... no dice. Any idea what I'm doing wrong? Does PHP have problems with doing string comparisons with non-English text?
Thanks!
Here is a code excerpt:
// Chop up HTML content into bits
$threadPieces = explode('</div>', $innerHTML);
// Chop up the HTML bits into data entries
$strippedThreadPieces = strip_tags($threadPieces[1]);
$threadInfo = explode('-', $strippedThreadPieces);
$threadTitleExists = trim($threadTitleExists, 'thread_title_');
$postername = "مراسل";
if (($threadTitleExists > 100000) && ($threadInfo[0] === $postername))
{
echo 'Thread title:';
echo strip_tags($threadPieces[0]);
echo '<p>';
}
else
{
}
I think the problem is the character set of your php file, try to save it using utf-8 character set.
The way I did this was using the function mb_ereg which is regular expression match with multibyte support.
Here's one I'm using
//from http://www.phperz.com/article/14/1029/31806.html
function mb_split_str($str) {
preg_match_all("/./u", $str, $arr);
return $arr[0];
}
//based on http://www.phperz.com/article/14/1029/31806.html, added percent
function mb_similar_text($str1, $str2, &$percent) {
$arr_1 = array_unique(mb_split_str($str1));
$arr_2 = array_unique(mb_split_str($str2));
$similarity = count($arr_2) - count(array_diff($arr_2, $arr_1));
$percent = ($similarity * 200) / (strlen($str1) + strlen($str2) );
return $percent;
}
So
$var = mb_similar_text('عمار', 'ياسر', $per);
output: $var = 2, $per = 25

PHP regex vs explode() for phone number

I have been messing around with some regular expressions, and I ran into a small hiccup with a more complicated version of my phone number formatting.
Here's what I am working with:
$number1 = '+1 (123) 1234567';
$number1 = '+966 (1) 1234567 x555';
These strings are actually being output from the MySQL query I created, and I love it.
However, I'm making a simple php function to auto-format the subscribers number from 1234567 to 123-4567.
I'm not too concerned about any number that doesn't start with +1. So I'm formatting US and Canadian numbers.
Here's what I attempted, if there was only 7 digits, and if the string starts with +1
<?php
function format_phonenumbers($phone){
if(empty($phone)){ return ''; }
$exploded = explode(' ',$phone);
$countrycode = $exploded[0];
$areacode = $exploded[1];
$number = $exploded[2];
$ext = (!empty($exploded[3])?$exploded[3]:'');
if($countrycode=='+1'){
$strphone = strlen($number);
if ($strphone == 7) { // auto-format US PHones
$prefix = substr($number,0,3);
$suffix = substr($number,-4);
}
$phone = $countrycode.' '.$areacode.' '.$prefix.'-'.$suffix.' '.$ext;
}
return $phone;
}
echo format_phonenumbers('+1 (714) 1234567'); // US domestic
echo '<br>';
echo format_phonenumbers('+966 (1) 1234567 x555'); // international
?>
This formats what I need, but I'm curious if anyone believes I can do this in a better way. Like using a regex checker, that finds anything after the parenthesis, but before an extension, rather than using the explode() function.
Something like:
function format_phonenumbers($phone)
{
return preg_replace_callback(
'/([)]\s*)(\d{3,3}(\d+)/',
function ($match) {
return $match[1] . $match[2] . '-' . $match[3];
},
$phone
);
}
This should work, but requires PHP 5.3.0 or higher (if not you'll have to use create_function). Its arguable if it is any better however.

Categories