【问题标题】:Eval alternative评估替代
【发布时间】:2013-02-01 17:43:28
【问题描述】:

这段代码可以用作计算器,但 codeacademy 的便签本告诉我 eval 是邪恶的。是否有另一种方法可以在不使用 eval 的情况下做同样的事情?

var calculate = prompt("Enter problem");
alert(eval(calculate));

【问题讨论】:

  • 您想将等式从字符串解析为工作代码吗?然后你需要构建一个解析器。
  • 而构建解析器并非易事。
  • @AdamRackis 确实如此,但处理中缀算术的东西并没有那么不好 - 它可能是最好的“我的第一个解析器”项目 :-)
  • @VisioN:实际上是eval
  • @VisioN 对于乳糖不耐症的人来说,这就像用马苏里拉奶酪代替切达干酪 :-)

标签: javascript math eval calculator


【解决方案1】:

eval 将字符串输入计算为 JavaScript,巧合的是,JavaScript 支持计算并理解 1+1,这使其适合用作计算器。

如果您不想使用eval,这很好,您必须自己解析该字符串,最后,自己进行计算(虽然不完全是您自己)。看看this math processor,它可以满足您的需求。

基本上你要做的是:

  1. 逐字符读取输入字符串(出现这种问题还是有可能的)
  2. 构建您想要执行的操作树
  3. 在字符串的末尾,您评估树并进行一些计算

例如你有"1+2/3",这可以评估为以下数据结构:

     "+"
     /  \
   "1"  "/"
       /   \
     "2"   "3"

然后您可以从上到下遍历该结构并进行计算。 一开始你有"+",左边有一个1,右边有一些表达式, 所以你必须先评估那个表达式。所以你转到"/" 节点,它有两个数字子节点。知道了这一点,您现在可以计算 2/3 并用其结果替换整个 "/" 节点。现在您可以再次向上计算“+”节点的结果:1 + 0.66。现在你用结果替换那个节点,剩下的就是表达式的结果。

关于这在您的代码中的外观的一些伪代码:

calculation(operator, leftValue, rightValue):
   switch operator {
      case '+': return leftValue + rightValue
      case '-': return 42
   }

action(node):
   node.value = calculation(node.operator, action(node.left) action(node.right))

您可能已经注意到,树的设计方式是尊重运算符优先级。 / 的级别低于 +,这意味着它首先得到评估。

无论您如何详细地执行此操作,基本上都是这样。

【讨论】:

  • 好吧,1+2/3 将导致1+(2/3),但不会导致(1+2)/3。所以答案将是1.6(6) 而不是3/3。这意味着您的数学处理器也应该考虑运算符优先级。
  • 哦,错了,是的。我本来打算这样写的。
【解决方案2】:

您可以通过过滤输入安全地将 eval 用于简单的算术计算器 - 如果您只接受数字、小数点和运算符(+、-、*、/),您不会遇到太多麻烦。如果您想要高级数学函数,最好使用解析器建议。

function calculate(){
    "use strict";
    var s= prompt('Enter problem');
    if(/[^0-9()*+\/ .-]+/.test(s)) throw Error('bad input...');
    try{
        var ans= eval(s);
    }
    catch(er){
        alert(er.message);
    }
    alert(ans);
}

calculate()

【讨论】:

    【解决方案3】:

    您可以使用 math.js 库中包含的表达式解析器:

    http://mathjs.org

    示例用法:

    mathjs.evaluate('1.2 / (2.3 + 0.7)');   // 0.4
    mathjs.evaluate('5.08 cm in inch');     // 2 inch
    mathjs.evaluate('sin(45 deg) ^ 2');     // 0.5
    mathjs.evaluate('9 / 3 + 2i');          // 3 + 2i
    mathjs.evaluate('det([-1, 2; 3, 1])');  // -7
    

    【讨论】:

      【解决方案4】:

      当我遇到这样的问题时,我会编写一些函数。也许这会有所帮助:

      data = [
        {id:1,val1:"test",val2:"test2",val2:"test3"},
        {id:2,val1:"test",val2:"test2",val2:"test3"},
        {id:3,val1:"test",val2:"test2",val2:"test3"}
      ];
      datakey = Object.keys(data[0]);
      // here's a fix for e['datakey[f]'] >> e[x]
      vix = function(e,f){
      	a = "string";
      	e[a] = datakey[f];
      	x = e.string;
      	end = e[x];
      	delete e.string;
      	return end;
      };
      // here's a fix to define that variable
      vox = function(e,f,string){
      	a = "string";
      	e[a] = datakey[f];
      	x = e.string;
      	end = e[x] = string;
      	delete e.string;
      };
      row = 2 // 3th row ==> {id:3,val1:"test",val2:"test2",val2:"test3"}
      column = 1 //datakey 2 ==> val1
      vox(data[row],column,"new value");
      alert(data[2].val1); //the value that we have changed

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-10
        • 1970-01-01
        • 2013-08-20
        • 1970-01-01
        • 2022-01-14
        相关资源
        最近更新 更多