【问题标题】:How do get input 2^3 to Math.pow(2, 3)?如何将输入 2^3 输入到 Math.pow(2, 3)?
【发布时间】:2017-02-09 23:18:05
【问题描述】:

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

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>

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

但我不知道如何将'^'之前和之后的值放入括号中。

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

【问题讨论】:

  • 只有x^y 的简单情况,其中x,y 是整数,使用简单的正则表达式非常可行。但是,正确解析 (2+34)^5 之类的内容显然更复杂。你能澄清一下你想要做什么吗?

标签: javascript math expression-evaluation


【解决方案1】:

对捕获组使用正则表达式:

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

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

(1+2)^3^3

这将需要编写一个递归下降解析器,这比我愿意在这里给出的答案要多得多。获取有关编译器设计的教科书以了解如何做到这一点。

【讨论】:

  • 这是一个理想的解决方案,因为它允许表达式具有多个操作
【解决方案2】:

我认为您无法通过简单的替换来做到这一点。

如果要解析中缀运算符,则构建两个堆栈,一个用于符号,另一个用于数字。然后依次走公式,忽略除符号、数字和右括号之外的所有内容。将符号和数字放入它们的堆栈中,但是当您遇到右括号时,取最后一个符号并将其应用于最后两个数字。 (我认为是 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))

【讨论】:

    【解决方案3】:

    把你的输入变成一个字符串然后做...

    var input = document.getElementById('value').value;
    var values = input.split('^'); //will save an array with [value1, value 2]
    var result = Math.pow(values[0], values[1]);
    console.log(result);
    

    仅当您的唯一操作是“^”时才这样做

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

    【讨论】:

      【解决方案4】:
      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) 随时都会支持它。

      【讨论】:

        【解决方案5】:

        正如这里的其他答案所说,您需要一个真正的解析器来正确解决这个问题。正则表达式将解决简单的情况,但对于嵌套语句,您需要递归解析器。对于提供此功能的 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]*
        

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

        【讨论】:

          【解决方案6】:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-10-28
            • 2021-04-08
            • 2021-01-12
            • 2014-09-17
            • 2021-05-07
            • 2021-05-30
            • 2016-11-16
            • 2017-12-29
            相关资源
            最近更新 更多