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
Related
I'm making a calculator for pipe fittings. The idea is that the user inputs the angle of the turn, then the calculator will tell you how many of what fittings to use. I have access to 8°, 11.25°, 22.5°, 45°, and 90° fittings. But, I can simplify it into 8° and 11.25° fittings, since 22.5°, 45°, and 90° are multiples of 11.25. I can take the # of 11.25 degree fittings, then use the following code to break it into larger fittings.
$num90 = floor($angle11 / 90);
$runningtotal = $angle11 - $num90 * 90;
$num45 = floor($runningtotal / 45);
$runningtotal = $runningtotal - $num45 * 45;
$num22 = floor($runningtotal / 22.5);
$runningtotal = $runningtotal - $num22 * 22.5;
$num11 = floor($runningtotal / 11.25);
$runningtotal = $runningtotal - $num11 * 11.25;
echo "You will need:";
echo "<br>";
echo "$num90 -- 90° fittings";
echo "<br>";
echo "$num45 -- 45° fittings";
echo "<br>";
echo "$num22 -- 22.5° fittings";
echo "<br>";
echo "$num11 -- 11.25° fittings";
Basically, I need to solve the equation:
"8x + 11.25y = angle"
Where "angle" is a known value, and X and Y are integers.
I've made a list of all the possible angles using these fittings, so the program will use the closest possible angle to their request (e.g. if they need a 150° turn, they'll be shown the fittings needed for a 150.5° connection, which is possible). That means that X and Y will be whole numbers. I already have the code to select the closest angle, I'm not worried about it.
I've looked into solutions for the Change Making Problem, which deals with something extremely similar. Most of the equations and algorithms they found go way over my head in terms of complexity. I'm a recent high school graduate, so my math level isn't as good as others.
How would I go about solving this equation? Is this maybe too complicated for me, a beginner? Am I overlooking some super simple solution?
Or, should I just use the wolframalpha API to offload the math onto their side?
Any help would be very appreciated!
Try this:
print_r(get_best_fit(150));
function get_best_fit($angle){
$a = 8;
$b = 11.25;
$best_diff = $angle;
$best_fit = [0,0];
for($x = 0; $x <= $angle/$a; $x++){
$y = round(($angle-$a*$x)/$b);
$diff = $angle-($x*$a+$y*$b);
if(abs($diff) < $best_diff){
$best_diff = abs($diff);
$best_fit = [$x,$y];
}
}
return $best_fit;
}
Output
Array ( [0] => 16 [1] => 2 )
So you would need 16 x 8 + 2 x 11.25.
I've got this spot of code that seems it could be done cleaner with pure math (perhaps a logarigthms?). Can you help me out?
The code finds the first power of 2 greater than a given input. For example, if you give it 500, it returns 9, because 2^9 = 512 > 500. 2^8 = 256, would be too small because it's less than 500.
function getFactor($iMaxElementsPerDir)
{
$aFactors = range(128, 1);
foreach($aFactors as $i => $iFactor)
if($iMaxElementsPerDir > pow(2, $iFactor) - 1)
break;
if($i == 0)
return false;
return $aFactors[$i - 1];
}
The following holds true
getFactor(500) = 9
getFactor(1000) = 10
getFactor(2500) = 12
getFactor(5000) = 13
You can get the same effect by shifting the bits in the input to the right and checking against 0. Something like this.
i = 1
while((input >> i) != 0)
i++
return i
The same as jack but shorter. Log with base 2 is the reverse function of 2^x.
echo ceil(log(500, 2));
If you're looking for a "math only" solution (that is a single expression or formula), you can use log() and then take the ceiling value of its result:
$factors = ceil(log(500) / log(2)); // 9
$factors = ceil(log(5000) / log(2)); // 13
I seem to have not noticed that this function accepts a second argument (since PHP 4.3) with which you can specify the base; though internally the same operation is performed, it does indeed make the code shorter:
$factors = ceil(log(500, 2)); // 9
To factor in some inaccuracies, you may need some tweaking:
$factors = floor(log($nr - 1, 2)) + 1;
There are a few ways to do this.
Zero all but the most significant bit of the number, maybe like this:
while (x & x-1) x &= x-1;
and look the answer up in a table. Use a table of length 67 and mod your power of two by 67.
Binary search for the high bit.
If you're working with a floating-point number, inspect the exponent field. This field contains 1023 plus your answer, except in the case where the number is a perfect power of two. You can detect the perfect power case by checking whether the significand field is exactly zero.
If you aren't working with a floating-point number, convert it to floating-point and look at the exponent like in 3. Check for a power of two by testing (x & x-1) == 0 instead of looking at the significand; this is true exactly when x is a power of two.
Note that log(2^100) is the same double as log(nextafter(2^100, 1.0/0.0)), so any solution based on floating-point natural logarithms will fail.
Here's (nonconformant C++, not PHP) code for 4:
int ceillog2(unsigned long long x) {
if (x < 2) return x-1;
double d = x-1;
int ans = (long long &)d >> 52;
return ans - 1022;
}
My question is how could I replace those if's with math formula?
if ($l <= 3500)
{
$min = 100;
}
elseif ($l <= 4000)
{
$min = 120;
}
elseif ($l <= 4500)
{
$min = 140;
}
elseif ($l <= 5000)
{
$min = 160;
}
As you see this is raising 20 for every 500 levels.
As you see this is raising 20 for every 500 levels.
Well, that's your formula right there.
$min = 100 + ceil(($l-3500)/500) * 20;
We start with 100, our base value and add that to the rest of the calculation.
$l starts with 3500 less.
We ceil() the result since we only want to jump when we pass the whole value.
We multiply that by 20.
If we want to address the case where $l is less than 3500 and set 100 as the minimum value, we also need to asset that $l-3500 is more than zero. We can do this as such:
$min = 100 + ceil(max(0,$l-3500)/500) * 20;
How did I get there?
What we're actually doing is plotting a line. Like you said yourself we go a constant amount for every constant amount. We have something called linear progression here.
Great, so we recognized the problem we're facing. We have an imaginary line to plot and we want integer values. What next? Well, let's see where the line starts?
In your case the answer is pretty straightforward.
if ($l <= 3500) {
$min = 100;
}
That's our starting point. So we know the point (3500,100) is on our line. This means the result starts at 100 and the origin starts at 3500.
We know that our formula is in the form of 100+<something>. What is that something?
Like you said, for every 500 levels you're raising 20. So we know we move 20/500 for every 1 level (because well, if we multiply that by 500 we get our original rule). We also know (from before) that we start from 3500.
Now, we might be tempted to use $min = 100 + ($l-3500) * (20/500); and that's almost right. The only problem here is that you only want integer values. This is why we ceil the value of level/500 to only get whole steps.
I tried to keep this with as little math terminology as possible, you can check the wikipedia page if you want things more formal. If you'd like any clarification - let me know
Here is my approach about this problem. It's not better than a single-line formula, but for sake of being modifiable, I generally decide this kind of solutions:
$min = 100;
for($i=3500; $i<=5000; $i+=500)
{
if($l <= $i) break;
$min += 20;
}
//Now $min has got desired value.
You can express the function as follows:
f(x) := a * x + b
The inclination of the line is calculated as:
a := 20 / 500
To find b you need to extrapolate a value that's on the line; in this case, that could be 3500 (x) and 120 (f(x)). That works out to be -40.
So the function has become:
f(x) := (20 / 500) * x - 40
There are two special cases:
Left of 3500 the value of f(x) must remain 100, even though f(x) is less.
The inclination is not continuous but discrete.
Both cases applied:
$min = max(100, ceil($l / 500) * 20 - 40)
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.
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.