숫자 값을 생성하기 위해 '1+1'
호출하지 않고 문자열 (예 :)에서 수학 표현식을 구문 분석하고 평가하는 방법은 eval(string)
무엇입니까?
이 예제에서는 함수가을 받아들이고 '1+1'
반환 하기를 원합니다 2
.
답변:
다음 과 같은 작업을 수행 할 수있는 JavaScript Expression Evaluator 라이브러리 를 사용할 수 있습니다.
Parser.evaluate("2 ^ x", { x: 3 });
math.eval('sin(45 deg) ^ 2');
결국 내 프로젝트 중 하나에 mathjs를 선택했습니다.
+ 또는-를 쉽게 수행 할 수 있습니다.
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';
console.log(
addbits(string)
)
더 복잡한 수학은 eval을 더 매력적으로 만들고 확실히 쓰기를 더 간단하게 만듭니다.
누군가 그 문자열을 파싱해야합니다. 인터프리터가 아니라면 (을 통해 eval
) 숫자, 연산자 및 수학 표현식에서 지원하려는 다른 모든 것을 추출하는 구문 분석 루틴을 작성하는 것이 당신이어야합니다.
따라서 .NET 없이는 (간단한) 방법이 없습니다 eval
. 보안에 대해 우려하는 경우 (파싱하는 입력이 제어하는 소스가 아니기 때문에) eval
?에 전달하기 전에 입력의 형식 (화이트리스트 정규식 필터를 통해)을 확인할 수 있습니다 .
더 짧은 정규 표현식을 사용하고 연산자 사이에 공백을 허용하는 @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);
});
}
같은 목적으로 BigEval 을 만들었습니다 .
식을 풀 때 Eval()
%, ^, &, ** (승수) 및! (계승). 표현식 내에서 함수와 상수 (또는 변수)를 사용할 수도 있습니다. 표현식은 JavaScript를 포함한 프로그래밍 언어에서 일반적으로 사용되는 PEMDAS 순서 로 해결됩니다 .
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
임의의 정밀도로 숫자를 처리하는 경우 산술에 해당 Big Number 라이브러리를 사용하도록 만들 수도 있습니다.
수학적 표현을 평가하기 위해 JavaScript 라이브러리를 찾고 있었고 다음 두 가지 유망한 후보를 찾았습니다.
JavaScript Expression Evaluator : 더 작고 가볍습니다. 대수식, 대체 및 여러 함수를 허용합니다.
mathjs : 복소수, 행렬 및 단위도 허용합니다. 브라우저 내 JavaScript 및 Node.js 모두에서 사용하도록 제작되었습니다.
저는 최근 Eval()
에 Reverse Polish Notation 의 표현을 평가하여 C #에서이 작업을 수행했습니다 ( 우리에게는 아닙니다 ... ). 어려운 부분은 실제로 문자열을 구문 분석하여 Reverse Polish Notation으로 바꾸는 것입니다. Wikipedia 및 의사 코드에 대한 훌륭한 예가 있으므로 Shunting Yard 알고리즘을 사용했습니다 . 둘 다 구현하는 것이 정말 간단하다는 것을 알았고 아직 해결책을 찾지 못했거나 대안을 찾고 있다면 이것을 권장합니다.
이것은이 문제를 해결하기 위해 방금 모아 놓은 작은 함수입니다. 한 번에 한 문자 씩 문자열을 분석하여 표현식을 작성합니다 (실제로는 꽤 빠릅니다). 이것은 모든 수학 식 (+,-, *, / 연산자로만 제한됨)을 취하고 결과를 반환합니다. 음수 값과 무제한 숫자 연산도 처리 할 수 있습니다.
남은 유일한 "해야 할 일"은 + &-전에 * & /를 계산하는 것입니다. 나중에 해당 기능을 추가 할 예정이지만 지금은 필요한 작업을 수행합니다.
/**
* 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;
}
간단하고 우아한 Function()
function parse(str) {
return Function(`'use strict'; return (${str})`)()
}
parse("1+2+3");
) -----
()`마지막으로이 대괄호?
parse('process.exit()')
.
for 루프를 사용하여 문자열에 잘못된 문자가 포함되어 있는지 확인한 다음 eval과 함께 try ... catch를 사용하여 계산에서 원하는 오류가 발생하는지 확인할 eval("2++")
수 있습니다.
function evaluateMath(str) {
for (var i = 0; i < str.length; i++) {
if (isNaN(str[i]) && !['+', '-', '/', '*', '%', '**'].includes(str[i])) {
return NaN;
}
}
try {
return eval(str)
} catch (e) {
if (e.name !== 'SyntaxError') throw e
return NaN;
}
}
console.log(evaluateMath('2 + 6'))
또는 함수 대신 설정할 수 있습니다. Math.eval
Math.eval = function(str) {
for (var i = 0; i < str.length; i++) {
if (isNaN(str[i]) && !['+', '-', '/', '*', '%', '**'].includes(str[i])) {
return NaN;
}
}
try {
return eval(str)
} catch (e) {
if (e.name !== 'SyntaxError') throw e
return NaN;
}
}
console.log(Math.eval('2 + 6'))
결국 양수와 음수를 합산하는이 솔루션을 사용했습니다 (정규식을 약간 수정하면 십진수에서도 작동합니다).
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 ()보다 빠른지 확실하지 않지만 작업을 여러 번 수행해야하므로 자바 스크립트 컴파일러의 인스턴스를 생성하는 것보다이 스크립트를 실행하는 것이 훨씬 더 편합니다.
return
표현의 내부에 사용할 수 없습니다, sum("+1")
반환 NaN이를 .
AutoCalculator https://github.com/JavscriptLab/autocalculate Calculate Inputs value and Output By using selector expressions
data-ac = "(# firstinput + # secondinput)"과 같은 출력 입력에 속성을 추가하기 만하면됩니다.
초기화 할 필요가 없습니다. data-ac 속성 만 추가하면됩니다. 동적으로 추가 된 요소를 자동으로 찾습니다.
또는 출력에 'Rs'를 추가하려면 중괄호 안에 추가하십시오. data-ac = "{Rs} (# firstinput + # secondinput)"
const operatorToFunction = {
"+": (num1, num2) => +num1 + +num2,
"-": (num1, num2) => +num1 - +num2,
"*": (num1, num2) => +num1 * +num2,
"/": (num1, num2) => +num1 / +num2
}
const findOperator = (str) => {
const [operator] = str.split("").filter((ch) => ["+", "-", "*", "/"].includes(ch))
return operator;
}
const executeOperation = (str) => {
const operationStr = str.replace(/[ ]/g, "");
const operator = findOperator(operationStr);
const [num1, num2] = operationStr.split(operator)
return operatorToFunction[operator](num1, num2);
};
const addition = executeOperation('1 + 1'); // ans is 2
const subtraction = executeOperation('4 - 1'); // ans is 3
const multiplication = executeOperation('2 * 5'); // ans is 10
const division = executeOperation('16 / 4'); // ans is 4
num
1을 곱 해야합니까?
다음은 문자별로 표현 문자를 반복하고 왼쪽 / 연산자 / 오른쪽을 점진적으로 추적하는 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);
}
(Function("return 1+1;"))()
.