14 ответов:
можно использовать JavaScript Expression Evaluator library, что позволяет вам делать такие вещи, как:
Parser.evaluate("2 ^ x", { x: 3 });или mathjs, который позволяет такие вещи, как:
math.eval('sin(45 deg) ^ 2');в итоге я выбрал mathjs для одного из моих проектов.
кто-то должен разобрать эту строку. Если это не интерпретатор (via
eval) тогда вам нужно будет написать процедуру синтаксического анализа для извлечения чисел, операторов и всего остального, что вы хотите поддержать в математическом выражении.итак, нет, нет никакого (простого) способа без
eval. Если вы беспокоитесь о безопасности (потому что вход, который вы анализируете, не из источника, который вы контролируете), возможно, вы можете проверить формат ввода (через фильтр регулярных выражений белого списка) перед тем, как передавая егоeval?
// вы можете сделать + или - легко:
function addbits(s){ var total= 0, s= s.match(/[+\-]*(\.\d+|\d+(\.\d+)?)/g) || []; while(s.length){ total+= parseFloat(s.shift()); } return total; } var string='1+23+4+5-30'; addbits(string)более сложная математика делает eval более привлекательным-и, конечно, проще писать.
Я пошел искать библиотеки JavaScript для оценки математических выражений и нашел этих двух перспективных кандидатов:
JavaScript Expression Evaluator: меньше и, надеюсь, больше легкий вес. Позволяет алгебраические выражения, замены и a количество функций.
mathjs: позволяет комплексные числа, матрицы и блоки, а также. Встроенный для использования как в браузере JavaScript, так и Узел.js.
Я недавно сделал это в C# (нет Eval () для нас...) путем вычисления выражения в обратной польской нотации (это самая легкая). Трудная часть фактически разбирает строку ths и превращает ее в обратную польскую нотацию. Я использовал алгоритм маневрового двора, так как есть отличный пример в Википедии и псевдокоде. Я нашел, что это очень просто реализовать оба, и я бы рекомендовал, если вы еще не нашли решение или ищете альтернативы.
Я создал BigEval С той же целью.
В решении выражений, он выполняет точно так же, какEval()и поддерживает такие операторы, как%,^,&, * * (мощность) и ! (факторный.) Вы также можете использовать функции и константы (или переменных) внутри выражения. Выражение решается в порядок PEMDAS, который является общим в языках программирования, включая JavaScript.var Obj = new BigEval(); var result = Obj.exec("5! + 6.6e3 * (PI + E)"); // 38795.17158152233 var result2 = Obj.exec("sin(45 * deg)**2 + cos(pi / 4)**2"); // 1 var result3 = Obj.exec("0 & -7 ^ -7 - 0%1 + 6%2"); //-7Он также может быть использован для использования этих библиотек большого числа для арифметики в случае, если вы имеете дело с числами с произвольной точностью.
Это небольшая функция, которую я собрал только сейчас, чтобы решить эту проблему - она строит выражение, анализируя строку по одному символу за раз (это на самом деле довольно быстро, хотя). Это займет любое математическое выражение (ограниченное только операторами+, -,*,/) и вернет результат. Он может обрабатывать отрицательные значения и неограниченное количество операций, а также.
единственное, что нужно сделать, это убедиться, что он вычисляет * & / перед + & -. Добавлю эту функциональность позже, но для теперь это то, что мне нужно...
/** * Evaluate a mathematical expression (as a string) and return the result * @param {String} expr A mathematical expression * @returns {Decimal} Result of the mathematical expression * @example * // Returns -81.4600 * expr("10.04+9.5-1+-100"); */ function expr (expr) { var chars = expr.split(""); var n = [], op = [], index = 0, oplast = true; n[index] = ""; // Parse the expression for (var c = 0; c < chars.length; c++) { if (isNaN(parseInt(chars[c])) && chars[c] !== "." && !oplast) { op[index] = chars[c]; index++; n[index] = ""; oplast = true; } else { n[index] += chars[c]; oplast = false; } } // Calculate the expression expr = parseFloat(n[0]); for (var o = 0; o < op.length; o++) { var num = parseFloat(n[o + 1]); switch (op[o]) { case "+": expr = expr + num; break; case "-": expr = expr - num; break; case "*": expr = expr * num; break; case "/": expr = expr / num; break; } } return expr; }
альтернатива отличному ответу @kennebec, используя более короткое регулярное выражение и позволяя пробелы между операторами
function addbits(s) { var total = 0; s = s.replace(/\s/g, '').match(/[+\-]?([0-9\.\s]+)/g) || []; while(s.length) total += parseFloat(s.shift()); return total; }использовать его как
addbits('5 + 30 - 25.1 + 11');обновление
вот более оптимизированная версия
function addbits(s) { return (s.replace(/\s/g, '').match(/[+\-]?([0-9\.]+)/g) || []) .reduce(function(sum, value) { return parseFloat(sum) + parseFloat(value); }); }
Я в конечном итоге пошел на это решение, которое работает для суммирования положительных и отрицательных целых чисел (и с небольшой модификацией регулярного выражения будет работать и для десятичных чисел):
function sum(string) { return (string.match(/^(-?\d+)(\+-?\d+)*$/)) ? string.split('+').stringSum() : NaN; } Array.prototype.stringSum = function() { var sum = 0; for(var k=0, kl=this.length;k<kl;k++) { sum += +this[k]; } return sum; }Я не уверен, что это быстрее, чем eval (), но поскольку мне приходится выполнять операцию много раз, мне гораздо удобнее запускать этот скрипт, чем создавать множество экземпляров компилятора javascript
попробовать nerdamer
var result = nerdamer('12+2+PI').evaluate(); document.getElementById('text').innerHTML = result.text();<script src="http://nerdamer.com/js/nerdamer.core.js"></script> <div id="text"></div>
Попробуйте Автокалькулятор https://github.com/JavscriptLab/autocalculate Вычислите входное значение и выход с помощью выражений селектора
просто добавьте атрибут для вашего выходного входа, например data-ac="(#firstinput+#secondinput)"
нет необходимости в какой-либо инициализации просто добавить атрибут data-ac только. Он автоматически обнаружит динамически добавленные элементы
добавить 'РС' с Выход просто добавить внутрь фигурных скоба data-ac= " {Rs} (#firstinput+#secondinput)"
Я считаю, что
parseIntи ES6 может быть полезно в этой ситуации==> таким образом:
let func = (str) => { let arr = str.split(""); return `${Number(arr[0]) + parseInt(arr[1] + Number(arr[2]))}`}; console.log(func("1+1"));главное здесь то, что
parseIntанализирует число с помощью оператора. Код может быть изменен в соответствии с соответствующими потребностями.
вот алгоритмическое решение, подобное jMichael, которое циклически проходит через символ выражения за символом и постепенно отслеживает влево/оператор/вправо. Функция накапливает Результат после каждого хода и находит символ оператора. Эта версия поддерживает только операторы ' + 'и' -', но написана для расширения другими операторами. Примечание: мы устанавливаем 'currOp' в '+' перед циклом, потому что мы предполагаем, что выражение начинается с положительного поплавка. На самом деле, в целом я делаю предположение, что ввод аналогичен тому, что будет поступать из калькулятора.
function calculate(exp) { const opMap = { '+': (a, b) => { return parseFloat(a) + parseFloat(b) }, '-': (a, b) => { return parseFloat(a) - parseFloat(b) }, }; const opList = Object.keys(opMap); let acc = 0; let next = ''; let currOp = '+'; for (let char of exp) { if (opList.includes(char)) { acc = opMap[currOp](acc, next); currOp = char; next = ''; } else { next += char; } } return currOp === '+' ? acc + parseFloat(next) : acc - parseFloat(next); }
const getAddition = (str) => { return str.split('+').reduce((total, num) => (total + num * 1), 0); }; const addition = getAddition('1+1');дополнительно 2.
Comments