Writing a function that "solves" the equation

I want to write a function that will allow me to "solve" the equation in js.

what i want (not in programming language):

function f(x) { 1 + x * x } var z = 2 var y = f(z) //y will be 5 as a number 

what i wrote in js:

 function P(cfg) { .... this.equation = "1 + x"; ....}; P.prototype.eqn = function(x) { var tmp = eval(this.equation); return tmp; }; .... P.prototype.draw = function() {.... for(var i = 0; i < z; i++) ctx.lineTo(i, this.eqn(i)); ....}; 

I also read that using eval in a loop is probably not a good idea, but I still haven't figured out another way (new to JS) ...

The problem with this code is that at least in FF var tmp will STILL contain the line from this.equation instead of the computed value.

I would appreciate any further insight!

Thank you for your time:)

EDIT: because my question was not formulated very well: after running the line var tmp = eval (this.equation); var tmp will hold STRING, which is equal to the string this.equation instead of the value of the desired solution y. Also I do not mean the solution, but I appreciate it, thanks for this advice :)

+6
source share
6 answers

Based on your example, I would say that you want to "evaluate the expression" rather than "solve the equation." You can find many guides to evaluate expression. I will break it briefly. You need to take a few steps.

Starting with your line "1 + x * x", you need to split it into tokens. In particular, divide it into: "1", "+", "x", "*", "x" . At this point, you can replace your variables ("x") with their literal values ​​("2"), giving you "1", "+", "2", "*", "2"

Now you need to parse the expression. Based on the order of PEMDAS operations, you need to create a tree data structure in which the first brackets are executed (material surrounded by brackets), then multiply and divide, and then add and subtract the latter. Analysis is often a daunting task, and you may need to compile a simpler BNF grammar (although you can probably find a grammar for simple math expressions with some search engines).

Then go through the tree, first in depth, evaluating operations as you move through the tree. Once you get to the top of the tree, you have your decision.

If instead you want to "solve the equation", you need something more complex, like Sage

+4
source

I used to use this expression evaluator . It seemed to work very well. It allows you to pass expressions to the parser, which returns an object of the function, which can then evaluate the input.

 var expr = Parser.parse("2 ^ x"); expr.evaluate({ x: 3 }); // 8 

It supports trigger functions (sin, cos, ect ...) and other convenient built-in functions like abs and ciel.

 var expr = Parser.parse("sin(x/2) + cos(x/2)") expr.evaluate({x: Math.PI / 2}); // 1 

Examples: http://silentmatt.com/javascript-expression-evaluator/

Code: https://github.com/silentmatt/js-expression-eval

Note that this lib does not use eval ().

+3
source

Not sure if I fully understand your question, but what about:

 var makeFunctionOfX = function(src) { return Function('x', 'return ' + src); }; 

Then you can say things like:

 var g = makeFunctionOfX('2 * x') var y = g(3); // y contains 6 

The huge advantage of this eval method is that the created Function does not have the magical ability to see variables in scope (therefore, you must explicitly pass its x as the parameter name).

+2
source

Using eval safe if you trust user input and work fine. (I have no idea what you mean by "var tmp will still have this.equation".)

 function FuncCreator(eqn){ this.eqn = eqn } FuncCreator.prototype.run = function(x,y,z){ return eval(this.eqn) } var add1 = new FuncCreator('1+x'); var result = add1.run(41); // 42 var complex = new FuncCreator('Math.sin(x*y) / Math.cos(z)'); var result = complex.run(3,4,5); // -1.891591285331882 

If you do not trust user input, you need to actually analyze the input and process it yourself. This is not trivial.

+2
source

You can use the expression parser from the math.js library and do something like this:

 var parser = math.parser(); var f = parser.eval('function f(x) = 1 + x * x'); // use the created function f in expressions: parser.eval('z = 2'); // 2 parser.eval('y = f(z)'); // 5 // or use the created function f in JavaScript: var z = 2; // 2 var y = f(z); // 5 

Function creation in math.js is currently limited, the loops and blocks needed to define more extensive functions are not yet supported.

+2
source

This is an old thread, but I wrote this equation calculator, but it does not solve algebraic equations. However, there is a function that allows you to provide an array containing the assigned variables. But this does not solve for variables that do not have an assigned value.

I probably did not redo every script, but it seems to work pretty well.

Edit: This would need to be changed to handle negative numbers. Other than that ... works great.

Here is the fiddle

 <!doctype html> <html> <head> <title>Javascript Equation Calculator</title> </head> <body> <input type="button" onclick="main()" value="calculate"><br> <input type="text" id="userinput"><br> <span id="result">Ready.</span><br> <script> function Calculator(){} String.prototype.replaceLast = function (what, replacement) { var pcs = this.split(what); var lastPc = pcs.pop(); return pcs.join(what) + replacement + lastPc; }; function inS(substr, str){return (str.indexOf(substr) > -1);} function arrayValueOrToken(arr, key, token) { if(key in arr) { return arr[key]; } return token; } function reduceEquation(inputStr) { console.log("reduceEquation Executed-----"); while(hasNest(inputStr)) { if(hasNest(inputStr)) { inputStr = inputStr.replace(")(",')*('); for(var i=0;i<=9;i++) { inputStr = inputStr.replace(i+"(",i+'*('); inputStr = inputStr.replace(")"+i,')*'+i); } var s = inputStr.lastIndexOf("("); var e = 0; for(i=s;i,inputStr.length;i++){if(inputStr[i]==")"){e=i+1;break;}} var eq = inputStr.substring(s,e); var replace = eq; eq = eq.replace(/[()]/g, ''); var substitution = solveEquation(eq); inputStr = inputStr.replaceLast(replace,substitution); } } return inputStr; } function solveEquation(eq) { console.log("solveEquation Executed-----"); eq = doFirstOrder(eq); eq = doLastOrder(eq); return eq; } function doFirstOrder(eq) { console.log("doFirstOrder Executed-----"); for(var i=0;i<eq.length;i++) { if(eq[i]=="*"){eq = solve(eq,"*");return doFirstOrder(eq);} if(eq[i]=='/'){eq = solve(eq,'/');return doFirstOrder(eq);} } return eq; } function doLastOrder(eq) { console.log("doLastOrder Executed-----"); for(var i=0;i<eq.length;i++) { if(eq[i]=="+"){eq = solve(eq,"+");return doLastOrder(eq);} if(eq[i]=="-"){eq = solve(eq,"-");return doLastOrder(eq);} } return eq; } function solve(eq, operator) { var setOp = operator; console.log("solve Executed-----"); var buildEq = "",var1 = true,done = false,char=""; var operators = "+-/*"; var ops = operators.replace(operator, '').split(''); var a=ops[0]; var b=ops[1]; var c=ops[2]; for(var i=0;i<eq.length;i++) { char = eq[i]; switch(true) { case(char==operator):if(var1===true){var1 = false;}else{done = true;}break; case(char==a): case(char==b): case(char==c):if(var1){char = ""; buildEq = "";}else{done = true;} } if(done){break;} buildEq = buildEq + char; } var parts = parts = buildEq.split(operator); var solution = null; if(operator=="+"){solution = parseFloat(parts[0]) + parseFloat(parts[1]);} if(operator=="-"){solution = parseFloat(parts[0]) - parseFloat(parts[1]);} if(operator=="*"){solution = parseFloat(parts[0]) * parseFloat(parts[1]);} if(operator=="/"){solution = parseFloat(parts[0]) / parseFloat(parts[1]);} return eq.replace(buildEq, solution); } function hasNest(inputStr){return inS("(",inputStr);} function allNestsComplete(inputStr) { var oC = 0, cC = 0,char=""; for(var i=0;i<inputStr.length;i++){char = inputStr[i];if(char=="("){oC+=1;}if(char==")"){cC+=1;}} return (oC==cC); } Calculator.prototype.calc = function(inputStr) { console.log("Calc Executed-----"); inputStr = inputStr.replace(/ /g, ""); inputStr = inputStr.replace(/\\/g, '/'); inputStr = inputStr.replace(/x/g, "*") inputStr = inputStr.replace(/X/g, "*") if(!allNestsComplete(inputStr)){return "Nested operations not opened/closed properly.";} inputStr=reduceEquation(inputStr); inputStr = solveEquation(inputStr); return inputStr; }; Calculator.prototype.calcWithVars = function(inputList) { if(inputList.length < 2){return "One or more missing arguments!";} var vars = []; var assocVars = []; var lastVarIndex = inputList.length - 2; var i = 0; var inputStr = inputList[inputList.length-1]; for(i=0;i<=lastVarIndex;i++) { vars.push(inputList[i].replace(/ /g, "")); } for(i=0;i<=vars.length-1;i++) { var vParts = vars[i].split("="); var vName = vParts[0]; var vValue = vParts[1]; assocVars[vName] = vValue; } inputStr = inputStr.replace(/ /g, ""); var eqVars = inputStr.replace(/\s+/g, ' ').replace(/[^a-zA-Z-]/g, ' ').replace(/\s\s+/g, ' '); if(inS(" ", eqVars)) { eqVars = eqVars.split(" "); } else{eqVars = [eqVars];} eqVars.sort(function(a, b){return a.length - a.length;}); var tempTokens = []; var tempCount = 1; for(i=0;i<eqVars.length;i++) { var eqVname = eqVars[i]; var substitution = arrayValueOrToken(assocVars, eqVname, "<unknown>"); if(substitution != "<unknown>") { inputStr = inputStr.replace(eqVname,substitution); } else { var tempToken = "#______#"+tempCount+"#______#"; tempCount++; tempTokens.push(tempToken + "?" + eqVname); inputStr = inputStr.replace(eqVname,tempToken); } } for(i=0;i<tempTokens.length;i++) { var tokenSet = tempTokens[i]; var tokenParts = tokenSet.split("?"); var token = tokenParts[0]; var variableName = tokenParts[1]; inputStr = inputStr.replace(token,variableName); } var answerName = "<unknown>"; var eq = inputStr; if(inS("=", inputStr)) { var eqParts = inputStr.split("="); answerName = eqParts[0]; eq = eqParts[1]; } eq = this.calc(eq); var result = []; for(i=0;i<eqVars.length;i++) { var v = arrayValueOrToken(assocVars, eqVars[i], "<unknown>"); if(v != "<unknown>") { result.push(assocVars[eqVars[i]]); } } result.push(eq); return result; }; function main() { var calculator = new Calculator(); elUserInput = document.getElementById('userinput'); console.log("input: "+ elUserInput.value); elResult = document.getElementById('result'); equation = elUserInput.value; result = calculator.calc(equation); console.log("result: "+ result); elResult.innerHTML = result; } </script> </body> </html> 
0
source

Source: https://habr.com/ru/post/944563/


All Articles