PHP Maths Equation Function - php

What i am really looking for is a maths equation function that takes in a string representing and equation and calculates the answer as a return type
For Example
"(((4 * 5) + 6) * 2) / 8"
OutPut: 6.5
So in coding tearms something like
print calc("(((4 * 5) + 6) * 2) / 8");
Is there already a class or a function that some angel has built or do i gota do it my self
Thanks

you can use eval() for that, it'll evaluate the argument as php code:
$result = eval("(((4 * 5) + 6) * 2) / 8"); // 6.5
print $result;

As cloudhead said, just fixed up.
$nums = "(((4 * 5) + 6) * 2) / 8";
eval("\$nums = $nums;");
echo $nums;

If you end up rolling your own, read Smart design of a math parser or Equation expression parser with precedence. With explicit parentheses as in your example the parser would be much simpler.

Related

PHP exp() not working. Getting an infinite number

Javascript: var random = Math.exp(Math.random() * Math.log(100 - 10 + 10)) + 10;
Edit: + 10 inside the log function was a typo.
Attempt for a PHP Equivalent: $random = exp(rand() * log(100 - 10 + 10)) + 10;
The latter returns false, where the first returns a number. The problem is definately the exponent function that behaves differently.
How can I fix this?
Math.random returns a number between 0 and 1.
rand() return a big integer. That's where the infinite comes from.
Edit
Documentation for rand() and Math.random
You can change your code as follows to overcome this:
$random = exp((rand(1, 1000)/1000) * log(100 - 10 + 10)) + 10;

Can someone explain this php function to me?

I'm trying to understand everything this PHP function does. A game has this code and I'm trying to determine how much XP it takes to level for each level.
function xpToNextLevel($level){
if($level == 0){
return 200;
}
$s = 500;
$m = 0xFFFF * ($level / 98);
$xp = floor((($m - $s) * ($level / 98)) + $s);
return $xp;
}
Thanks!
I think it's great to look over other people's code (open-source or with permission that is) to better understand the language. While I understand the down-voting, as google would have been a good resource to figure this out, I'll try to explain it the best I can.
To help explain it, I have rewritten a bit of your code for you.
function xpToNextLevel($level){
if($level == 0){
return 200;
}
$d = $level / 98;
$s = 500;
$m = 65535 * $d; /* 65535 is equivalent to 0xFFFF */
$k = $m - $s; /* takes (0xFFFF * ($level / 98)) - $s */
$dk = $k * $d; /* takes ($m - $s) * ($level/98) */
$unroundedXP = $dk + $s; /* adds (($m-$s) * ($level/98)) to $s */
$xp = floor($unroundedXP); /* rounds the experience down. */
return $xp;
}
so, I know in your comment you asked about the level 4. Let's trace through that!
4 != 0 // thus we continue.
4/98 = 2/49 /*which is roughly ~0.04082, but for the sake of accuracy, I'll leave it as 2/49 */
65535 * (2/49) = ~2674.89795
2674.89795 - 500 = 2174.89795
2174.89795 * 2/49 = ~88.771345
88.771344 + 500 = 588.771344 //This is the unrounded experience
Experience = 588
The floor function basically rounds to the lowest integer. In positive numbers, this means we take the number and toss out everything behind the decimal point. So the number returned is roughly 588. I say roughly because a computer would be more exact about it.
By the way, I believe this is most comparable to a "Arithmetic Series." More information about that can be found here: http://mathworld.wolfram.com/ArithmeticSeries.html
So, let's simplify the formula mathematically. Following formulas are not a PHP code, but pure mathematics!
xp = ((65535 * (level / 98)) - 500) * (level / 98) + 500
... which simplifies to ...
xp = (65535 / 98^2) * level^2 - (500 / 98) * level + 500
... which is approximately equivalent to ...
xp = 6.8 * level^2 - 5.1 * level + 500
As You can see, the amount of experience needed for next level grows quadratically along the formula above.

Algorithm for difference of products of large integers

I'm searching for an algorithm to solve differences of the type ab-cd, where a, b, c, and d are integers at the edge of the type capacity, i.e. ab overflows or loses digits depending on the actual representation on the machine. I cannot use arbitrary precision math; one of the platforms will be a SQL database.
I consider something like decomposing the product into (a'+a'')b-(c'+c'')d and then somehow iterate the way down. But probably there is a much more efficient method or at least a clever idea how to do the decomposition. Unfortunately in most cases a,b; c,d; a,c; b,d are coprime, so reduction at least is not simple.
Any ideas?
WARNING
This method is only partially functional. There are cases that it can't solve.
Taken from your text:
I'm searching for an algorithm to solve differences of the type ab-cd,
where a, b, c, and d are integers at the edge of the type capacity,
As I understand you want to calculate (a * b) - (c * d) avoiding a numeric overflow. And you want to solve this with an algorithm.
The first thing we need to recognize is that the result of (a * b) - (c * d) may not fit in the data type. I'll not try to solve those cases.
So, I'll search for different ways to calculate "ab-cd". What I've found is this:
(a * b) - (c * d) = ((a - c) * b) - (c * (d - b))
You can re-order the variables to get different products and therfore increasing the chance of finding a case that will allow you to calculate the operation without the dreaded numeric overflow:
((a - d) * b) - (d * (c - b))
((b - c) * a) - (c * (d - a))
((a - c) * b) - (c * (d - b))
((b - d) * c) - (b * (c - a))
((a - d) * c) - (a * (c - b))
((b - c) * d) - (b * (d - a))
((a - c) * d) - (a * (d - b))
Also notice that this are still differences of products, meaning that you can apply them recursively until you find one that works. For example:
Starting with:
(a * b) - (c * d)
=>
Using the transformation:
((a - d) * b) - (d * (c - b))
=>
By substitution:
(e * b) - (d * f)
=>
Rinse an repeat:
((e - f) * b) - (f * (d - b))
Of course we need to make sure we aren't going to run into a numeric overflow by doing this. Thankfully it is also possible to test if a particular product will cause a numeric overflow (without actually doing the product) with the following approach:
var max = MaxValue;
var min = MinValue;
if (a == 0 || b == 0)
{
return false;
}
else
{
var lim = a < 0 != b < 0 ? min : max;
if ((a < 0 == b < 0) == a < 0)
{
return lim / a > b;
}
else
{
return lim / a < b;
}
}
Also, it is also possible to test if a particular difference will cause a numeric overflow (without actually doing the difference) with the following approach:
var max = MaxValue;
var min = MinValue;
if (a < 0 == b < 0)
{
return true;
}
else
{
if (a < 0)
{
if (b > 0)
{
return min + b < a;
}
else
{
return min - b < a;
}
}
else
{
if (b > 0)
{
return max - b > a;
}
else
{
return max + b > a;
}
}
}
With that it is possible to pick an expression from the eight above that will allow you to calculate without the numeric overflow.
But... Sometimes none of those works. And it seems to be that there are cases where not even their combinations works (ie. rinse and repeat dosn't work)*. Maybe there are other identities that can complete the picture.
*: I did try using some heuristic to explore the combinations and also did try random exploration, there is the risk that I didn't pick good heuristics and I didn't have "luck" with the random. That's why I can't tell for sure.
I want to think that I've done some progress... But with respect to the original problem I've ultimately failed. May be I'll get back to this problem when I have more time... or may be I'll just play video games.
The standard way I know of to address this type of issues is to do what humans do with numbers beyond one digit, which is the limit of our natural counting with fingers. We carry numbers forward.
For example, let's say the limit of numbers in your numeric calculator is 256 (2^8). To get the difference of (243*244)-(242*245), we would need to decompose the numbers into
Label | Part 1 (shifted 2 right) | Part 2 (remainder)
a 2 43
b 2 44
c 2 42
d 2 45
You'd need an array to store the individual digits of the result, or a string. I think an array is faster, but a string more convenient and visible (for debugging).
(a*b)-(c*d)
=> a1*b1 shift4 + a1*b2 shift2 + a2*b1 shift2 + a2*b2
- c1*d1 shift4 + c1*d2 shift2 + c2*d1 shift2 + c2*d2
=> 987654321 (right-aligned string positioning)
+ 4xxxx
+ 88xx
+ 86xx
+ 1892
- 4xxxx
- 90xx
- 84xx
- 1890
==========
2
A naive implementation would work through each step independently, pushing each digit into place and carrying it forward where necessary. There are probably tomes of literature about optimizing these algorithms, such as breaking this into array slots of 2 digits each (since your register of number-limit 256 can handle the addition of 2 2-digit numbers easily).
If your products are near the limits of Int32 you can use Int64.
You can use BC Math Functions to work with large number which on both 32 bit & 64 bit systems
Example Of Large Numbers
$a = "4543534543543534543543543543545";
$b = "9354354546546756765756765767676";
$c = "5654656565656556565654656565656";
$d = "4556565656546546546546546356435" ;
var_dump(calculate($a, $b, $c, $d));
Output
string '257010385579862137851193415136408786476450997824338960635377204776397393100227657735978132009487561885957134796870587800' (length=120)
Function Used
function calculate($a, $b, $c, $d)
{
return bcmul(bcmul(bcmul(bcsub($a, $c),bcsub($a, $d)),bcsub($b, $c)),bcsub($b, $d));
}
After playing a little bit more I found a simpler algorithm following my original idea. It may be somewhat slower than the combined multiplication because it requires real multiplication and division instead of only shifts and addition, but I didn't benchmark it so far concerning the performance in an abstract language.
The idea is the following rewrite ab-cd = (a'+q*d)b-cd = a'b-(c-qb)d = a'b-c'd
The algorithm seems to convert the fastest if you order ab-cd as a>b and c>d, i.e. reduce the biggest numbers and maximize q.
q=(int)floor((a>c)? a/d : c/b);
a -= q*d;
c -= q*b;
Now reorder and start again. You can finish as soon as all numbers are small enough for safe multiplication, any number becomes smaller than 2 or even negative, or you find the same value for any of the numbers on both sides.

PHP algorithm to solve a system of linear equations of grade 1

I have a system of equations of grade 1 to resolve in PHP.
There are more equations than variables but there aren't less equations than variables.
The system would look like bellow. n equations, m variables, variables are x[i] where 'i' takes values from 1 to m. The system may have a solution or not.
m may be maximum 100 and n maximum ~5000 (thousands).
I will have to resolve like a few thousands of these systems of equations. Speed may be a problem but I'm looking for an algorithm written in PHP for now.
a[1][1] * x[1] + a[1][2] * x[2] + ... + a[1][m] * x[m] = number 1
a[2][1] * x[1] + a[2][2] * x[2] + ... + a[2][m] * x[m] = number 2
...
a[n][1] * x[1] + a[n][2] * x[2] + ... + a[n][m] * x[m] = number n
There is Cramer Rule which may do it. I could make 1 square matrix of coefficients, resolve the system with Cramer Rule (by calculating matrices' determinants) and than I should check the values in the unused equations.
I believe I could try Cramer by myself but I'm looking for a better solution.
This is a problem of Computational Science,
http://en.wikipedia.org/wiki/Computational_science#Numerical_simulations
I know there are some complex algorithms to solve my problem but I can't tell which one would do it and which is the best for my case. An algorithm would use me better than just the theory with the demonstration.
My question is, does anybody know a class, script, code of some sort written in PHP to resolve a system of linear equations of grade 1 ?
Alternatively I could try an API or a Web Service, best to be free, a paid one would do it too.
Thank you
I needed exactly this, but I couldn't find determinant function, so I made one myself. And the Cramer rule function too. Maybe it'll help someone.
/**
* $matrix must be 2-dimensional n x n array in following format
* $matrix = array(array(1,2,3),array(1,2,3),array(1,2,3))
*/
function determinant($matrix = array()) {
// dimension control - n x n
foreach ($matrix as $row) {
if (sizeof($matrix) != sizeof($row)) {
return false;
}
}
// count 1x1 and 2x2 manually - rest by recursive function
$dimension = sizeof($matrix);
if ($dimension == 1) {
return $matrix[0][0];
}
if ($dimension == 2) {
return ($matrix[0][0] * $matrix[1][1] - $matrix[0][1] * $matrix[1][0]);
}
// cycles for submatrixes calculations
$sum = 0;
for ($i = 0; $i < $dimension; $i++) {
// for each "$i", you will create a smaller matrix based on the original matrix
// by removing the first row and the "i"th column.
$smallMatrix = array();
for ($j = 0; $j < $dimension - 1; $j++) {
$smallMatrix[$j] = array();
for ($k = 0; $k < $dimension; $k++) {
if ($k < $i) $smallMatrix[$j][$k] = $matrix[$j + 1][$k];
if ($k > $i) $smallMatrix[$j][$k - 1] = $matrix[$j + 1][$k];
}
}
// after creating the smaller matrix, multiply the "i"th element in the first
// row by the determinant of the smaller matrix.
// odd position is plus, even is minus - the index from 0 so it's oppositely
if ($i % 2 == 0){
$sum += $matrix[0][$i] * determinant($smallMatrix);
} else {
$sum -= $matrix[0][$i] * determinant($smallMatrix);
}
}
return $sum;
}
/**
* left side of equations - parameters:
* $leftMatrix must be 2-dimensional n x n array in following format
* $leftMatrix = array(array(1,2,3),array(1,2,3),array(1,2,3))
* right side of equations - results:
* $rightMatrix must be in format
* $rightMatrix = array(1,2,3);
*/
function equationSystem($leftMatrix = array(), $rightMatrix = array()) {
// matrixes and dimension check
if (!is_array($leftMatrix) || !is_array($rightMatrix)) {
return false;
}
if (sizeof($leftMatrix) != sizeof($rightMatrix)) {
return false;
}
$M = determinant($leftMatrix);
if (!$M) {
return false;
}
$x = array();
foreach ($rightMatrix as $rk => $rv) {
$xMatrix = $leftMatrix;
foreach ($rightMatrix as $rMk => $rMv) {
$xMatrix[$rMk][$rk] = $rMv;
}
$x[$rk] = determinant($xMatrix) / $M;
}
return $x;
}
Wikipedia should have pseudocode for reducing the matrix representing your equations to reduced row echelon form. Once the matrix is in that form, you can walk through the rows to find a solution.
There's an unmaintained PEAR package which may save you the effort of writing the code.
Another question is whether you are looking mostly at "wide" systems (more variables than equations, which usually have many possible solutions) or "narrow" systems (more equations than variables, which usually have no solutions), since the best strategy depends on which case you are in — and narrow systems may benefit from using a linear regression technique such as least squares instead.
This package uses Gaussian Elimination. I found that it executes fast for larger matrices (i.e. more variables/equations).
There is a truly excellent package based on JAMA here: http://www.phpmath.com/build02/JAMA/docs/index.php
I've used it for simple linear right the way to highly complex Multiple Linear Regression (writing my own Backwards Stepwise MLR functions on top of that). Very comprehensive and will hopefully do what you need.
Speed could be considered an issue, for sure. But works a treat and matched SPSS when I cross referenced results on the BSMLR calculations.

How to solve a math equation in a programming language?

I need help to solve this formula ((n * 2) + 10) / (n + 1) = 3, preferably in PHP. (The numbers 2, 10 and 3 should be variables that can be changed.)
I'm able to solve this equation on paper quite easily. However, when I try to implement this in PHP, I'm not sure where to start. I've done several Google queries and searches on here and nothing seems to help. I'm missing the proper approach to deal with this problem.
Any tips and pointers would be great, and if you provide the exact code, please explain how you got to this result.
You're wanting to solve an equation, not implement it. There's a difference. Implementing the equation would be as simple as typing it in. You'd probably want to make it an equality operator (==) though.
Equation solvers are complicated, complicated things. I wouldn't try to make one when there are such good ones ( http://en.wikipedia.org/wiki/Comparison_of_computer_algebra_systems ) lying around.
You can use http://pear.php.net/package/PHP_ParserGenerator/redirected to parse the math expressions into a syntax tree, then do the maths.
((n * 2) + 10) / (n + 1) = 3 would look like:
The idea is to bring on the right subtree (here ...) all the numbers, and on the left all the unknownws, just as you'd do on paper.
In the end you'll have:
+
/ \
n -7
which is 0. And there you have your solution, for any math expression (with one unknown variable).
I'll leave the algorithm to you.
<?php
// ((x * n) + y)/(n + 1) = z)
// => n=(y-z)/(z-x)
function eq ($x=0,$y=0,$z=0)
{
if ($z!=$x)
{
$n=($y-$z)/($z-$x);
} else
{
$n='NAN';
}
return $n;
}
?>
(My algebra is old and flakey but I think this is right)
how about using brute-force??!?! might be slow and not exact:
$step = 0.00001;
$err = 0.1; //error margin
$start = 0;
$response = 3;
for($i = $start;$i <= 3;$i += $step){
if((($i * 2) + 10) / ($i + 1) >= $response - $err){
echo "the answer is $i";
}
}
You could improove this answer.. on every loop you could calculate the distance between the current answer and the desired answer, and adjust the parameters acording to that..
This reminds me my old A.I. class =)
Good Luck
Here's how to solve that equation in C# with the Symbolism computer algebra library:
var n = new Symbol("n");
(((n * 2) + 10) / (n + 1) == 3)
.IsolateVariable(n)
.Disp();
The following is displayed on the console when that code is executed:
n == 7

Categories