18

Is there a JavaScript library or function that will solve equations for variables?

Such as 9 = 3 + x and solve for x. But it should also solve more advanced equations that include sine, cosine, and tangent.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Will
  • 17,297
  • 7
  • 45
  • 48

5 Answers5

11

I'd like to propose nerdamer. It can algebraically solve up to quartic functions and it can numerically solve a range of functions. Another library to consider is Algebrite.

//solve linear equations
var x = nerdamer.solve('(x+1)*3=x-6', 'x');
console.log(x.toString());
//quadratic
var x2 = nerdamer.solve('x^2-8x+15', 'x');
console.log(x2.toString());
//quadratic algebraically
var x3 = nerdamer.solve('x^2-ax+3*b', 'x');
console.log(x3.toString());
//multiple roots
var x4 = nerdamer.solve('x^6+41*x^5+652*x^4+5102*x^3+20581*x^2+40361*x+30030', 'x');
console.log(x4.toString());
//functions - numerically around to zero up to a predefined range
var x5 = nerdamer.solve('cos(x)^2+sin(x-1)', 'x');
console.log(x5.toString());
//solve a system of linear equations
var x6 = nerdamer.solveEquations(['2x+y=7', 'x-y+3z=11', 'y-z=-1']);
console.log(x6.toString());
//solve a system of nonlinear equations
var x7 = nerdamer.solveEquations(['3*x^2/y=2', 'z*x*y-1=35', '5*z^2+7=52']);
console.log(x7.toString());
<script src="https://cdn.jsdelivr.net/npm/nerdamer@latest/nerdamer.core.js"></script>
<script src="https://cdn.jsdelivr.net/npm/nerdamer@latest/Algebra.js"></script>
<script src="https://cdn.jsdelivr.net/npm/nerdamer@latest/Calculus.js"></script>
<script src="https://cdn.jsdelivr.net/npm/nerdamer@latest/Solve.js"></script>
jiggzson
  • 435
  • 1
  • 4
  • 13
9

You can approximate the solution by doing what excel calls "Goal Seek" - testing values for x until both sides of the equation approximately match. You can do this by splitting the equation by the "=" sign, replacing each occurence of x with a value, evaling both sides, and determining if the difference falls below a certain threshold. While relatively simple, there are flaws to this method though (other than the fact that it is an approximation), for example the algorithm may think the two sides are converging when in fact it is just a local min/max and will diverge after the difference falls just below your threshold. You'll also need to test multiple start points to solve equations with more than one solution.

For a program to actually solve an equation as a human would (by rearranging the two sides of the equation and applying inverse functions, derivatives/integrals and whatnot) is far more complex, and somehow feels entirely proprietary ;)

David Tang
  • 86,742
  • 28
  • 159
  • 145
4

A quick search turns up algebra.js and js-solver. I don't know anything about them, but they seem legit. algebra.js has a nice OOP API, but doesn't appear to handle trigonometric functions.

orlade
  • 1,916
  • 4
  • 20
  • 31
2

Look at the script at Newton's Method Program for f(x)=0. It solves the equation using Newton's tangent method.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
kaharas
  • 567
  • 2
  • 15
  • 39
0

Ceres.js can find the solution to an array of equations of the form f(x) = 0. It is ported from C++ to JavaScript with Emscripten. The file is a bit large but if you need a really high performance solver this is your best bet. It runs in web-assembly so the speed is high. Here is an example:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>

<h2>Powell Function</h2>
<p>This is an example of the solution of the powell function using Ceres.js</p>

<textarea id="demo" rows="40" cols="170">
</textarea>

<script type="module">
    import {Ceres} from 'https://cdn.jsdelivr.net/gh/Pterodactylus/Ceres.js@master/Ceres-v1.5.3.js'

    var fn1 = function f1(x){
        return (x[0]+10*x[1]);
    }

    var fn2 = function f2(x){
        return (Math.sqrt(5)*(x[2]-x[3]));
    }
    
    var fn3 = function f3(x){
        return Math.pow(x[1]-2*x[2],2);
    }
    
    var fn4 = function f4(x){
        return Math.sqrt(10)*Math.pow(x[0]-x[3],2);
    }
    
    
    let solver = new Ceres()
    solver.add_function(fn1) //Add the first equation to the solver.
    solver.add_function(fn2) //Add the second equation to the solver.
    solver.add_function(fn3) //Add the third equation to the solver.
    solver.add_function(fn4) //Add the forth equation to the solver.
    //solver.add_callback(c1) //Add the callback to the solver.
    //solver.add_lowerbound(0,1.6) //Add a lower bound to the x[0] variable
    //solver.add_upperbound(1,1.7) //Add a upper bound to the x[1] variable
    
    solver.promise.then(function(result) { 
        var x_guess = [1,2,3,4] //Guess the initial values of the solution.
        var s = solver.solve(x_guess) //Solve the equation
        var x = s.x //assign the calculated solution array to the variable x
        document.getElementById("demo").value = s.report //Print solver report
        solver.remove() //required to free the memory in C++
    })
</script>
</body>
</html>