There is a field in which the amount is entered, various calculations are applied to Germans (for example, take a percentage of the amount and divide by 2) to calculate the commission Calculations in javascript, the formula is described in the DB field

How to make something universal?

For example, enter 100 - the value (100/10) * 4 + 810 =?, For another, for example, simply - / 2 or something else. To get the division fields, percentages, additions and everything to handle is too rough. The field has its own problems. There are more intervals, entered 100 - at output 10, entered from 101 to 1000 - 20. Here, okay, you can describe

How to deal with formulas I can not find the best option. That it was possible to submit and calculate javascript? Maybe there is something like regular expressions, but in terms of formulas, not data validation

  • one
    you provide in the formula some "variables", the lines that will be replaced with data when executed and then eval - Mike

4 answers 4

So we need a lot of different functions from one variable.

var f1body = 'return (x/10)*4 + 810;'; var f1 = new Function('x', f1body); var f2 = new Function('x', 'return x/2;'); var f3 = new Function('x', 'if (x < 101) return 10; if (x < 1001) return 20; return 30;'); var summa = 500; alert(f1(summa)); alert(f2(summa)); alert(f3(summa)); 

new Function as you can guess creates a function from a string. The first argument is the name of the parameters of the future function (in our case only one parameter). The second argument is the body of the function.

Do I have to say that the function bodies can be stored in the database and loaded as needed?

  • Not a bad way. But we must understand that in such a "head-on" solution it is impossible for the formulas to start the user in the database - otherwise it is a ready-made XSS (unless the formulas are individual). - Pavel Mayorov pm
  • So what to do? Whoever does not risk, he himself develops parsers of formulas (although it is not that difficult in fact). - Sergey
  • In this case there is no risk. There is a safe and unsafe code. - Pavel Mayorov
  • The risk is that the encoder may accidentally or maliciously encod a dangerous code. After all, in principle, no solutions can provide any guarantees against hazards. And there is no way to start the evals and functions in the sandbox so that they don’t pull their little hands where they are not supposed to? - Sergey
  • This is not a "risk". This is a vulnerability. - Pavel Mayorov

The most correct solution is still the use of a parser of mathematical formulas. If you yourself can not compose, you can find ready. Here, for example, http://mathjs.org/
The most difficult thing here is that Есть ещё интервалы, ввел 100 - на выходе 10, ввел от 101 до 1000 - 20 .
But you can probably come up with something.

    You can make several fields (custom quantity?) To enter values. And in the formula itself, write them in any convenient way. For example, (a/800 + b*1.5) . Accordingly, when calculating a formula, first read the variable values ​​from the input fields and substitute it into the string — with the usual replace or regular expression (for example, you might get a string like (200/800 + 300*1.5) ). And then feed the resulting formula in eval ().

    Just recommend the values ​​somehow screened. The most reliable way, perhaps, would be to remove from them all characters except the ones allowed: digits, full stop, comma, plus, minus, letters 'E' and 'e' (English and Russian are possible). After deletion, all commas are converted to points. If you plan to introduce mathematical expressions as values, then you can also leave in them the signs of operations and parentheses.

    • eval and string substitutions - evil - Pavel Mayorov
    • non-argued subjective opinion. - Marsel Yalalov
    • especially after the comment that new Function is a good way. - Marsel Yalalov

    Algorithm already described, I can offer an implementation option:

    Store formulas in the following format, where {{0}} is the first value, {{1}} is the second, and so on:

     var expression = "100 - {{0}} * (100 / 10) + {{1}}"; 

    The same array with values ​​(how and where to store is up to you, you can also in a database as a string, and then use eval to get an array), for example:

     var values = [100, 800]; 

    And the function that replaces the "template" with the value:

     // подставляем значения из массива в формулу var getFormula = function getFormula(str, values) { return values.reduce(function (str, number, i) { return str.replace('{{'+i+'}}', number); }, str); }; // getFormula(expression, values); "100 - 100 * (100 / 10) + 800" // getFormula("{{0}} * 5", [-2]); "-2 * 5" 

    And the last step in the simplest version:

     var parsedExpression = getFormula(expression, values); var finishValue = eval(parsedExpression); // -100 

    Of course there are a lot of nuances (processing invalid data, processing negative numbers, etc.), but for example, the implementation should be enough.

    • eval and string substitutions - evil - Pavel Mayorov
    • @ pavel-mayorov new Function() is a good option, and eval is evil? :) - saaaaaaaaasha
    • Of course, ideally, you can write your own formula parser, but for an example of a simple implementation, you can also use eval , and if the data is validated, then there should be no problems. - saaaaaaaaasha
    • Yes, that is right. The function is faster; besides, it will be more correct to work with "wrong" values. - Pavel Mayorov
    • Agree that in the context of this task "speed" will be minimal. Moreover, in the formulation of the question there were no statements that it is necessary to cite as an example the most optimal variant in terms of speed. besides, it will be more correct to work with the "wrong" values, please give an example, I can’t think of it right away. - saaaaaaaaasha