如何输入2 ^ 3到Math.pow(2,3)?

时间:2017-02-09 23:18:05

标签: javascript math expression-evaluation

我有这个简单的计算器脚本,但它不允许电源^。



function getValues() {
    var input = document.getElementById('value').value;

    document.getElementById('result').innerHTML = eval(input);

}

<label for="value">Enter: </label><input id="value">

  <div id="result">Results</div>

  <button onclick="getValues()">Get Results</button>
&#13;
&#13;
&#13;

我尝试使用input = input.replace( '^', 'Math.pow(,)');

但我不知道如何在&#39; ^&#39;之前获得价值。并进入括号后。

示例:(1 + 2)^ 3 ^ 3应该给出7,625,597,484,987

6 个答案:

答案 0 :(得分:2)

将正则表达式与捕获组一起使用:

&#13;
&#13;
input = '3 + 2 ^3';
input = input.replace(/(\d+)\s*\^\s*(\d+)/g, 'Math.pow($1, $2)');
console.log(input);
&#13;
&#13;
&#13;

这仅在参数只是数字时才有效。它不会使用子表达式或重复它,如

(1+2)^3^3

这需要编写一个递归下降的解析器,这比我愿意在这里提出答案的工作要多得多。获取有关编译器设计的教科书,以了解如何执行此操作。

答案 1 :(得分:1)

我认为你不能用简单的替换来做到这一点。

如果要解析中缀运算符,可以构建两个堆栈,一个用于符号,另一个用于数字。然后顺序走公式,忽略符号,数字和右括号之外的所有内容。将符号和数字放入堆栈中,但是当遇到关闭的paren时,请使用最后一个符号并将其应用于最后两个数字。 (由Dijkstra发明,我认为)

const formula = '(1+2)^3^3'


const symbols = []
const numbers = []

function apply(n2, n1, s) {
  if (s === '^') {
    return Math.pow(parseInt(n1, 10), parseInt(n2, 10))
  }
 
  return eval(`${n1} ${s} ${n2}`)
}

const applyLast = () => apply(numbers.pop(), numbers.pop(), symbols.pop())

const tokenize = formula => formula.split(/(\d+)|([\^\/\)\(+\-\*])/).filter(t => t !== undefined && t !== '')

const solver = (formula) => {
  const tf = tokenize(formula)

  for (let l of formula) {
    const parsedL = parseInt(l, 10)
    if (isNaN(parsedL)) {
      if (l === ')') {
        numbers.push(applyLast())
        continue
      } else {
        if (~['+', '-', '*', '/', '^'].indexOf(l))
          symbols.push(l)
        continue
      }
      
    } 
    numbers.push(l)
  }
  
  while (symbols.length > 0)
    numbers.push(applyLast())
  
  return numbers.pop()
}

console.log(solver(formula))

答案 2 :(得分:0)

将您的输入变为字符串并执行...

{{1}}

仅当您的唯一操作是'^'

时才会这样

编辑:编辑后看到示例,这不再有效。

答案 3 :(得分:0)

function getValues() {
    var input = document.getElementById('value').value;

    // code to make ^ work like Math.pow
    input = input.replace( '^', '**');

    document.getElementById('result').innerHTML = eval(input);

}

**运算符可以替换大多数现代浏览器中的Math.pow函数。每天推出的下一版Safari(v10.1)都支持它。

答案 4 :(得分:0)

正如其他答案所述,你需要一个真正的解析器才能正确解决这个问题。正则表达式将解决简单的情况,但对于嵌套语句,您需要一个递归解析器。对于Javascript,提供此功能的库是peg.js

在您的情况下,online version中给出的示例可以快速扩展以处理权限:

Expression
  = head:Term tail:(_ ("+" / "-") _ Term)* {
      var result = head, i;

      for (i = 0; i < tail.length; i++) {
        if (tail[i][1] === "+") { result += tail[i][3]; }
        if (tail[i][1] === "-") { result -= tail[i][3]; }
      }

      return result;
    }

Term
  = head:Pow tail:(_ ("*" / "/") _ Pow)* { // Here I replaced Factor with Pow
      var result = head, i;

      for (i = 0; i < tail.length; i++) {
        if (tail[i][1] === "*") { result *= tail[i][3]; }
        if (tail[i][1] === "/") { result /= tail[i][3]; }
      }

      return result;
    }

// This is the new part I added
Pow
  = head:Factor tail:(_ "^" _ Factor)* {
      var result = 1;
      for (var i = tail.length - 1; 0 <= i; i--) {
          result = Math.pow(tail[i][3], result);
      }
      return Math.pow(head, result);
    }

Factor
  = "(" _ expr:Expression _ ")" { return expr; }
  / Integer

Integer "integer"
  = [0-9]+ { return parseInt(text(), 10); }

_ "whitespace"
  = [ \t\n\r]*

它返回输入字符串7625597484987的预期输出(1+2)^3^3

答案 5 :(得分:0)

以下是此问题的基于Python的版本,使用pyparsing的解决方案:changing ** operator to power function using parsing?