IT Share you

JavaScript에서 문자열을 수학 표현식으로 평가

shareyou 2020. 12. 3. 20:50
반응형

JavaScript에서 문자열을 수학 표현식으로 평가


숫자 값을 생성하기 위해 '1+1'호출하지 않고 문자열 (예 :)에서 수학 표현식을 구문 분석하고 평가하려면 어떻게해야 eval(string)합니까?

그 예로, 나는 함수가 동의 할 '1+1'및 반환 2.


다음 과 같은 작업을 수행 할 수있는 JavaScript Expression Evaluator 라이브러리 를 사용할 수 있습니다.

Parser.evaluate("2 ^ x", { x: 3 });

또는 다음 과 같은 것을 허용하는 mathjs .

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';
addbits(string)

더 복잡한 수학은 eval을 더 매력적으로 만들고 확실히 쓰기를 더 간단하게 만듭니다.


누군가 그 문자열을 파싱해야합니다. 인터프리터가 아니라면 (을 통해 eval) 숫자, 연산자 및 수학 표현식에서 지원하려는 다른 모든 것을 추출하는 구문 분석 루틴을 작성하는 것이 당신이어야합니다.

따라서 아니요, eval. 보안에 대해 우려하는 경우 (파싱하는 입력이 제어하는 ​​소스가 아니기 때문에) eval?에 전달하기 전에 입력의 형식 (화이트리스트 정규식 필터를 통해)을 확인할 수 있습니다 .


같은 목적으로 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 라이브러리를 사용하도록 만들 수도 있습니다.


더 짧은 정규 표현식을 사용하고 연산자 사이에 공백을 허용하는 @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);
        });
}

수학적 표현을 평가하기 위해 JavaScript 라이브러리를 찾고 있었고 다음 두 가지 유망한 후보를 찾았습니다.

  • JavaScript Expression Evaluator : 더 작고 가볍습니다. 대수식, 대체 및 여러 함수를 허용합니다.

  • mathjs : 복소수, 행렬 및 단위도 허용합니다. 브라우저 내 JavaScript 및 Node.js 모두에서 사용하도록 제작되었습니다.


나는 최근에 Reverse Polish Notation (그것은 쉬운 비트)의 표현을 평가함으로써 C #에서 이것을했습니다 (우리에게는 Eval () 없음 ...). 어려운 부분은 실제로 문자열을 구문 분석하여 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 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 ()보다 빠른지 확실하지 않지만 작업을 여러 번 수행해야하므로 자바 스크립트 컴파일러 인스턴스를 생성하는 것보다이 스크립트를 실행하는 것이 훨씬 더 편합니다.


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>


AutoCalculator https://github.com/JavscriptLab/autocalculate Calculate Inputs value and Output By using selector expressions

data-ac = "(# firstinput + # secondinput)"과 같은 출력 입력에 속성을 추가하기 만하면됩니다.

No Need of any initialization just add data-ac attribute only. It will find out dynamically added elements automatically

FOr add 'Rs' with Output just add inside curly bracket data-ac="{Rs}(#firstinput+#secondinput)"


I believe that parseInt and ES6 can be helpful in this situation

==> in this way:

let func = (str) => {
let arr = str.split("");
return `${Number(arr[0]) + parseInt(arr[1] + Number(arr[2]))}`};
console.log(func("1+1"));

The main thing here is that parseInt parses the number with the operator. Code can be modified to the corresponding needs.


Here is an algorithmic solution similar to jMichael's that loops through the expression character by character and progressively tracks left/operator/right. The function accumulates the result after each turn it finds an operator character. This version only supports '+' and '-' operators but is written to be extended with other operators. Note: we set 'currOp' to '+' before looping because we assume the expression starts with a positive float. In fact, overall I'm making the assumption that input is similar to what would come from a calculator.

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');

addition is 2.

참고URL : https://stackoverflow.com/questions/2276021/evaluating-a-string-as-a-mathematical-expression-in-javascript

반응형