Bootstrap 如何在JavaScript计算器中解析和处理数学表达式?

mm5n2pyu  于 12个月前  发布在  Bootstrap
关注(0)|答案(3)|浏览(440)

用javascript计算像3+1*sin(20)*e^3这样的表达式的最佳方法是什么?
首先,我不想使用内置的数学函数。实际上,我已经为powersquare rootsincosexponential等定义了自己的函数。
我正在寻找的是一种解析表达式的好方法,这样我就可以将它们传递给我创建的这些函数。我知道JavaScript中有一个eval()函数可以用来计算输入表达式,但我不确定它是否适合这个上下文。
我应该使用eval()吗?如果是,在这种情况下如何使用它?如果不是,那么解析数学表达式的更合适的方法是什么?这不是学校布置的作业,只是个疑问。

rqqzpn5f

rqqzpn5f1#

使用第三方库

在真实的生活中,您可能希望使用math.js这样的库来为您进行计算。
要使用此库,请首先将其包含在HTML中:

<script src='path/to/math.js'></script>

然后,你可以使用math.eval方法来计算你的表达式:

math.eval('3+1*sin(20)*e^3');

也就是说,如果20是以弧度表示的值。由于它可能是以度表示的值,因此需要进行以下小调整:

math.eval('3+1*sin(20 deg)*e^3');

因为你明确地说你不想使用内置的数学函数,我怀疑你正在做一个学校作业。请注意,在StackOverflow上提交学校作业是不受欢迎的,因为它被认为是一种作弊形式。
但我们别管这事继续吧?!

独自一人

第一步:内置数学函数计算

在真实的生活中的项目中,你应该始终使用内置的数学函数或第三方库(如math.js),这些库在后台使用内置的数学函数。这是因为内置的数学函数都是100%可靠和性能优化。
不可能创建自己的等效内置数学函数,其可靠性和性能优化程度与内置函数相同,因此永远没有充分的理由不使用内置函数。但是既然你明确要求了,让我们忽略它,看看如何在没有内置数学函数的情况下做事情。我假设这也暗示了您不想使用math.js或任何其他库。
使用JavaScript的内置函数,你可以像这样计算你的表达式:

3+1*Math.sin(20)*Math.pow(Math.E,3)

使用的内置函数:

这里,同样重要的是,只有当20是以弧度为单位的值时,这才为真。由于20可能是一个度数值,你可能想定义自己的基于度数的sin函数,如下所示:

var dsin = function() {
  var piRatio = Math.PI / 180;
  return function dsin(degrees) {
    return Math.sin(degrees * piRatio);
  };
}();

现在,将Math.sin替换为dsin

3+1*dsin(20)*Math.pow(Math.E,3)

在任何真实的世界的应用程序中,this将是最好的计算3+1*sin(20)*e^3

第二步:将内置的数学函数替换为自己的函数

现在,当你真的,真的,真的看起来不想使用内置函数时,下一步就是用一个自己编写的等效函数替换每个内置函数。通常情况下,有多个数学路径朝向同一个目标。
例如,你可以像这样递归地编写pow函数:

var pow = function(base, exp) {
  if (exp == 0)
    return 1;
  else
    return base * power(base, exp - 1);
}

迭代实现:

var pow = function(base, exp) {
  var result = 1;
  while(exp--) {
    result *= base;
  }
  return result;
}

现在怎么办,你问。!您会问,如何在不依赖Math.sin的情况下实现dsin?!
嗯……一点点研究告诉你,你可以计算sin,使用公式sin(x) = x - x^3 / 3! + x^5 / 5! - x^7 / 7! + x^9 / 9! - ...
在JavaScript中,这将是这样的:

var sin = function(x) {
    var t1 = -1,t2 = 3,v1 = x,v2 = v1 + 1,it = 0;
    while (it < 10) {
        v2 = v1 + (t1 * pow(x, t2) / function(n){
        j = 1;
        for(i=1;i<=n;i++)
            j = j*i;
            return j;
        }(t2));
        t1 = -1 * t1;
        t2 += 2;
        v1 = v2;
        it++;
    }
    return v2;
}

您可能注意到我将阶乘计算放在lambda函数中。一个更优雅的解决方案是将lambda函数放在一个单独的函数中,因为您可能在其他地方需要它。
现在,你只需要把所有的碎片拼在一起,然后把它们 Package 在一个漂亮的对象中:

var Calc = (function(){
    return {
        E : 2.718281828459045,
        pow : function (base, exp) {
            var result = 1;
            while (exp--) {
                result *= base;
            }
            return result;
        },
        fact : function(n){
            j = 1;
            for(i=1;i<=n;i++)
                j = j*i;
            return j;
        },
        sin : function(x) {
            var t1 = -1,t2 = 3,v1 = x,v2 = v1 + 1,it = 0;
            while (it < 10) {
                v2 = v1 + (t1 * this.pow(x, t2) / this.fact(t2));
                t1 = -1 * t1;
                t2 += 2;
                v1 = v2;
                it++;
            }
            return v2;
        },
        dsin : function() {
            var piRatio = Math.PI / 180;
            return function dsin(degrees) {
                return Math.sin(degrees * piRatio);
            };
        }()
    };
})();

你可以像这样使用这些对象的方法:

3+1*Calc.dsin(20)*Calc.pow(Calc.E,3)

第三步:解析

如果你真的希望你的应用程序直接读取像3+1*sin(20)*e^3这样的表达式,你不应该使用eval()。相反,您应该编写自己的解析器。
正确的方法是首先编写一个标记器,将表达式转换为语法树。然后,将语法树传递给解释器,该解释器通过运行在步骤1中创建的计算函数来处理语法树。
要深入了解如何构建语法树和解释器,您可以查看this tutorial

5jdjgkvh

5jdjgkvh2#

我写了一个解析器,它可以满足你的需要。它被称为SwanJS,它不使用evalnew Function
安装:

npm install @onlabsorg/swan-js

用途:

const swan = require('@onlabsorg/swan-js');  // It works also in the browser
const evaluate = swan.parse("3 + 1 * sin(20) * e**3");
const context = swan.createContext({
   sin: Math.sin,  // or your own sin function
   e: Math.E
});
const value = await evaluate(context);

如果您不喜欢**作为幂运算符,您可以更改它,但这并没有很好的文档记录。看看/lib/interpreter.js,看看如何定义一个新的语法,或者问我,如果你喜欢。

shstlldc

shstlldc3#

如果你想要更多的数学功能,除了standard JavaScript math library,那么你可能想使用第三方库,如math.js
要使用此库,请首先将其包含在HTML中:

<script src='path/to/math.js'></script>

然后,你可以使用math.eval方法来计算你的表达式:

math.eval('3+1*sin(20)*e^3');

相关问题