Parse math operations with PHP - php

I am working on a project where I need to make a function that will parse the 4 default math operations (addition, subtraction, multiplication, division). It would be nice if the function could parse operations between brackets.
So, a must is that the function first check for multiplication and division operations (should check for that after it parser all operations between brackets if they exist, and that rule should apply for bracket operations [the biggest problem is that the brackets can contain brackets]). After doing all multiplication and division operations, it should do all addition and subtraction operations. The final number should be returned by functions.
Another nice addition would be a RegExp string that will check for math operations.
Thanks in advance!

This should be pretty secure:
function do_maths($expression) {
eval('$o = ' . preg_replace('/[^0-9\+\-\*\/\(\)\.]/', '', $expression) . ';');
return $o;
}
echo do_maths('1+1');

You could use eval() (WARNING: be sure what enters is a math operation and not some other arbitrary input or php code).
$input = "3 + (4 - 2 * 8) / 2";
eval('$result = ' . $input . ';');
echo "The result is $result";

there was a similar problem
How to evaluate formula passed as string in PHP?
you can try to use Class: Eval Math from php classes
http://www.phpclasses.org/package/2695-PHP-Safely-evaluate-mathematical-expressions.html

I can recommend https://github.com/andig/php-shunting-yard which is a PSR-0 compatible implementation of the Shunting Yard algorithm.

Regular expressions aren't the answer here; I suggest using an expression tree where all terminal nodes are constants or variables, and the rest of the nodes are operators. For example, 2 + 3 * 4 becomes:
+ --- 2
|
--- * --- 3
|
--- 4
Then, you evaluate the expression by using a depth-first traversal. In PHP it's sort of difficult to represent trees, but you could either use a built-in library as a commenter suggested or represent them using an associative array of arrays.

if you want a truly safe math parser, then eval won't do it. bcParserPHP can do it. It is implemented in PHP and does not use eval, thus it is very secure.

Related

PHP - How to eval math with big integer result?

I have a problem like this
when i eval this
$a='820725059 + 35 * 4082615 + 6209777 - 6476390779 * 3376849 + 3 - 8089 * 3967379273 - 0 * 55111452';
eval('return ('.$a.');');
i got this result -2.1901884886788E+16
instead of -21901884886788304
i know about BCMath, but how to calculate multiple operation like this?
Note:
My problem is about print out as BIG INT
Check if you are using 32bit or 64bit PHP
echo PHP_INT_SIZE; //4 is 32bit, 8 is 64bit
32bit won't handle this integer, for 64bit the result is -21901884886788304
if you have to use 32bit, try using GMP, and parse the integer yourself (good luck...)
Another solution is to write very basic Python program (or any other language that handles large numbers easily) and send it as an argument with exec function and let the other language to parse it for you (Python can handle very large numbers easily)
I assume that the line "how to calculate multiple operation like this?" means "how to write a calculator for arbitrary user-submitted math expressions?", which is why you use eval in first place.
If you use eval over unsanitized user-submitted input, you fail, remember this as a rule of thumb.
You just can't solve this with eval anyway, you have to use BCMath operations if you want to work with bignums.
Proper solution is to tokenize the input and construct the tree of math operations, essentially writing an interpreter for simple language for describing math expressions.
Here is result of 5 seconds of googling for something already done before: https://github.com/michellesanver/Calculator You can take her work and replace usage of plain math operators in classes like Addition with BCMath methods.

What is the purpose of XOR with zero

Taken from here: http://php.net/manual/en/function.base-convert.php#105414
function rome($N){
$c='IVXLCDM';
for($a=5,$b=$s='';$N;$b++,$a^=7)
for($o=$N%$a,$N=$N/$a^0;$o--;$s=$c[$o>2?$b+$N-($N&=-2)+$o=1:$b].$s);
return $s;
}
What is the purpose of XOR $a^0; here? (4th line)
Deleting it doesn't seem to make any difference. Check it out at: http://goo.gl/K6TwQI
You'll commonly see people use bitwise operators to implicitly convert expressions to an integer because of the way the underlying language works. This is mainly because these operations are blazing fast and avoid function calls, etc.
Because XOR doesn't affect the integer part of the variable, my best best is that this is just being used to ensure $a is always evaluated as an integer.
Here's an example.

How do I go about converting a math equation into php?

I am not so good at maths and I'm looking to transfer 3 math equations to php functions.
I've tried looking up how to individually do each part of the equation in php but I keep getting strange results so I must be doing something wrong.
Is there a php function for exponential growth?
The image with the equations are here:
http://i.imgur.com/zIhMEEu.jpg
Thanks
For the second equation this is what I have:
$rank = 50;
$xp = log(24000 * (2^($rank/6) - 1));
echo $xp;
The number is too small for this to be correct. I'm also not sure how to convert the 'ln 2' into PHP. The log() function seemed to come up under 'natural logarithm to php' search.
There are various functions that need to be combined in order to create these equations. The log function performs logarithm operations in a base of your choice (or ln if you do not provide a base). The pow function performs exponentiation.
Your equations would be:
function rank($xp) {
return floor(6 * log((xp * log(2) / 24000 + 1), 2));
}
function xp($rank) {
return floor(24000 * (pow(2, (rank / 6)) - 1) / log(2));
}
function kills($rank) {
return floor(xp($rank) / 200);
}
There are a few more parentheses there than absolutely needed, for clarity's sake.
Mathematical notations in general are considerably more compact and expressive than most programming languages (not just PHP) due to the fact that you can use any symbol you can think of to represent various concepts. In programming, you're stuck calling functions.
Also, I'm not sure what the various hardcoded numbers represent, or if it makes sense to change them, in the context of the formula, but you might want to think about setting them up as extra parameters to the function. For example:
function kills($rank, $killsPerXp = 200) {
return floor(xp($rank) / $killsPerXp);
}
This adds clarity to the code, because it lets you know what the numbers represent. At the same time, it allows you to change the numbers more easily in case you are using them in multiple places.

php scientific notation format

Trying to format a scientific number in PHP:
sprintf(%'1.2E',$var)
This gets me to 5.01E+1
I am trying to print 2 digits after the + sign
The parser requires the number format to be:
5.01E+01 instead of 5.01E+1
Is it possible to achieve this format with sprintf?
Is there any other method that can achieve this?
Thanks for looking
I couldn't find a way to do it solely with sprintf but I believe the following would be closer to the "correct" way to do it. The following calculates the exponent from the base-10 logarithm.
You can then pass the original value (dividing by 10 to the power of the exponent) and the exponent to the sprintf function as a float and an integer respectively. You can force the positive + sign remembering that it counts towards the character / padding length.
function scientificNotation($val){
$exp = floor(log($val, 10));
return sprintf('%.2fE%+03d', $val/pow(10,$exp), $exp);
}
demo / test cases :
scientificNotation(5.1); // 5.10E+00
scientificNotation(50.1); // 5.01E+01
scientificNotation(500.1); // 5.00E+02
scientificNotation(0.0051); // 5.10E-03
There is no built-in method as far as I know. But with a little bit of Regex black magic you can do something like this:
preg_replace('/(E[+-])(\d)$/', '${1}0$2', sprintf('%1.2E',$var));
Notice that I just wrapped your call to sprintf() with an appropriate call to preg_replace(). If the regular expression does not match it will leave the output from sprintf() as is.
The above answers both work great.
Also found out I can use:
$var_formatted = shell_exec("printf '%1.2E' $var");
which could be the cleanest given the script has the permissions to execute commmands.
The E+nn format is the default output format for the linux shell printf.
From the shell:
:~$ echo `printf '%1.2E' 500`
5.00E+02
:~$ echo `printf '%1.2E' 5`
5.00E+00
:~$ echo `printf '%1.2E' 0.05`
5.00E-02

Why a full stop, "." and not a plus symbol, "+", for string concatenation in PHP?

Why did the designers of PHP decide to use a full stop / period / "." as the string
concatenation operator rather than the more usual plus symbol "+" ?
Is there any advantage to it, or any reason at all? Or did they just like to? :o)
PHP's syntax is influenced by Perl, and . is the string concatenation operator in Perl.
In a weakly typed language there are advantages to having a different string concatenation and numeric addition operators: which one you use will influence which type the language coerces the variables to.
As it happens, Perl 6 will use a tilde ~ instead of a dot . for string concatenation, because . will be used for object member access. So it seems the designers of Perl now think it was a bad choice.
Perhaps, in Perl and PHP's early, non-Object-Oriented days, it seemed like as good a choice as any. Maybe the designers of both languages never envisaged them becoming strong OO languages.
As for whether PHP will one day ditch its -> member access syntax for ., who knows?
The most obvious reason would probably be that PHP inherits a lot of its syntax from Perl - and Perl uses a dot (.) for string concatenation.
But, we can delve deeper into it and figure out why this was implemented in Perl - the + operator is most commonly used for mathematical equations - it's only used for concatenation in languages in which the variable type can define the way in which the operator works (simple explanation, example is C#)
var intAddition = 1 + 2;
Console.WriteLine(intAddition); // Prints 3
var stringConcat = "1" + "2";
Console.WriteLine(stringConcat); // Prints "12"
^ As you can see, the + operator is used both for concatenation and addition in C#.
Perhaps the reasoning goes lower level and is due to the boolean algebra of logic gates - + means OR in logic gates, whereas . is used as the AND operator - which makes sense when it comes to string concatenation.
It makes sense to have two separate operators, one for concatenation and one for addition - it's just unfortunate that these two can be mixed up due to other languages.
I am not a PHP expert, but, how else do you do differentiate that last two lines?
$first = 100;
$second = 20;
$stringresult = $first . $second; // "10020"
$arithmeticresult = $first + $second; // 120
Logically + is used for numbers. While a dot is used to concatenate two sentences (strings) in a paragraph for example. Hence dot is used to concatenate strings. So it is pretty logical i believe. It is better that way...
Douglas Crockford thinks that + for Concatenation is a Bad Idea:
JavaScript has its share of design errors, such as the overloading of + to mean both
addition and concatenation with type coercion
The use of the dot as string concatenation operator in PHP probably dates back to Perl. Remember that PHP once was nothing more than a bunch of Perl scripts.
Also it makes sense to have distinct string concatenation and addition operators, especially in weakly-typed languages. There are enough pitfalls in PHP already to shoot yourself in the foot, you don't need to add another one.
I would too prefer to use a full stop instead of a plus sign because I usually associate + with mathematical equations.
For Example "this is a string " + 56 + 20
This would be very confusing for both the compiler/interpreter and the developer.
However the disadvantage to using full stop for concatenation operator is that it is just a dot on the screen and sometimes you can't see whether is it in the string or outside the string.
This doesn't answer the question, just wanted to share something.
From PHP Manual: String Operators, someone posted this which I find rather interesting. Notice how the space plays a part in the output.
Excerpt:
If you attempt to add numbers with a concatenation operator, your result will be the result of those numbers as strings.
<?php
echo "thr"."ee"; //prints the string "three"
echo "twe" . "lve"; //prints the string "twelve"
echo 1 . 2; //prints the string "12"
echo 1.2; //prints the number 1.2
echo 1+2; //prints the number 3
?>
+ should always be defined as a commutative operation (i.e., A+B = B+A). In the case of string concatenation, this is not the case ("foo" + "bar" != "bar" + "foo"). As such, + is not a good operator to use for the concatenation operation. Whether or not the language authors had this in mind when they used . instead (which is close to the multiplication operator, for which commutativity need not hold) remains to be seen, but it was a good decision nonetheless.
Here is a bit of historical context.
The PHP language started out as a set of Perl scripts.
As such, PHP gets most of it's syntax from Perl.
Perl, and by extension PHP, has untyped variables.
"5" == 5
"5" + 5 == 10
"5" . 5 == 55
To be able to tell the difference between addition and concatenation, they had to be two different operators.
Perl copied the method access operator from C ->.
This was before many of the more modern programming languages started to use . for method access.
Concatenation is one of the more common operations, and should use fewer characters. According to Huffman coding.
. was one of the few characters available for this use. The only other one that would make sense to use is ~, which is probably why that is now the Perl 6 concatenation operator.
While this isn't the historical reason it maybe show you why it is good to have a separate operator for addition and concatenation in the case of PHP.
The reason is what we see in JavaScript. We use the + character for concatenation and addition too. In PHP we have a separate operator for the two which is important for dynamically typed languages where implicit type conversion also present.
In PHP
echo 5 + 1; //6
echo 5 . 1; //51
echo "5" + 1; //6
echo "5" . 1; //51
This isn't surprising for anyone because we always explicitly stated whether we want to add or concatenate the two variable. Or in other words if we think about them as numbers or as strings.
In JavaScript
console.log( 5 + 1); //6
console.log("5" + 1); //51
console.log( 5 + "1"); //51
console.log("5" + "1"); //51
Without the knowledge of how implicit type conversions happen under the hood, in many cases (especially if they are complex) surprising results can happen, because we don't know what will be the outcome, because it isn't explicitly stated.
In Python
Python also uses the + operator for concatenation and for addition too, but it doesn't let implicit type conversion to happen. You have to explicitly mark the type conversion.
print 5 + 1 //6
print "5" + 1 //TypeError: cannot concatenate 'str' and 'int' objects
We have to do type conversion to make it work: a + int(b)
All in all
If we think about it, we can see that almost the same thing happens in PHP what we see in Python but instead of explicitly marking the type conversion, we mark with the operator that how we see the variables in terms of types.
I guess it is so you can concatenate numbers with strings?
$i=100;
$str="hello";
$str2 = $str.$i
Since you don't declare variable types, with a + it could give a result of 100 instead of "hello100."

Categories