Javascript是否会违反数学PEMDAS惯例?

时间:2012-03-29 02:16:27

标签: javascript math operator-precedence

我被教导在数学中我们用缩写BODMAS来评估事物 括号,订单(权力),分部,乘法,加法,减法。

据我所知,在Javascript中,*/具有相同的优先权。 +-也会这样做。 并且使用左关联性。

从我能想到的几个例子中,它似乎同样有效,产生与BODMA相同的结果。

看起来在数学规则的实际情况中,首先进行加法或减法无关紧要。是否可以在5-2 + 3之前完成附加或减法可能很重要。而对于除法和乘法,似乎只有一个问题,当除法像9/3*4这样的乘法时,则必须首先进行除法。并且Javascript在该实例中首先执行。

但也许有一个例子可以打破它!它给标准数学带来了不同的结果。

Javascript可以破坏逻辑数学规则吗?

UPDATE -

为了回答自己,在数学时,有人说,PEDMAS D和M优先级相同,从左到右完成。并且同上A和S.你说它们是左联的,即隐含括号的地方。因此,编程语言“实现PEDMAS”的优先级/优先级,DM和AS是左关联的,完全遵循PEDMAS规则。因此,如果有任何数学规则的破坏,则不是来自M,D,A,S的相关性,这与(常规)数学相同。此外,在数学中,一元减去这里是 - PEUDMAS所以-5 ^ 2 = - (5 ^ 2)= - 25。指数优先于一元减去。虽然javascript可能正确。显然,javascript破坏规则中的浮点,如某些答案中所示,尽管这不是我想到的,因为我的想法纯粹是PEDMAS,但似乎括号与浮点数有所不同,他们不应该在那里正常的数学,如我接受的答案所示。

4 个答案:

答案 0 :(得分:4)

唯一的问题是浮点数,其中一个除法的近似值非常大。一个实际的例子是,这将始终警告错误:

var a = 0.1;
var b = 0.2;
var c = 0.3;
if((a+b)+c == a+(b+c))
    alert("true");
else
    alert("false");

所以基本上问题在于Number对象,但没有实现理论数学。作为程序员,您可能理解前后增量的差异和运算符的顺序,所以我真的不明白为什么你给出了程序员逻辑适用的例子9/3*4,并且实际上很冗长数学。

最后你寻求的答案(可能只是出于好奇)是你所知道的数学的实际逻辑在JavaScript中没有改变,只是来自这种语言根源的一些错误仍然困扰着我们。

答案 1 :(得分:3)

  

我想知道,如果javascript可以产生不同的结果   标准数学说。

哦,是的。 Javascript中的数字由the IEEE double floating point表示。因为计算机只有很多内存,所以使用Javascript(或任何编程语言)do not have infinite precision

Wikipedia provides a striking example两个完全等效的公式如何在实际计算机上产生非常不同的结果。对于近似pi,可以使用以下Javascript实现该页面上显示的两个递归公式:

function iteration_verA(t)
{
    return (Math.sqrt(t*t+1)-1)/t;
}

function iteration_verB(t)
{
    return t/(Math.sqrt(t*t+1)+1);
}

function calculate_pi()
{
    document.write("<table border=\"1\"><tr><td>Iteration Number</td>");
    document.write("<td>Using Version A</td><td>Using Version B</td></tr>");

    var tA = 1/Math.sqrt(3);
    var tB = 1/Math.sqrt(3);
    for(i = 0; i < 30; ++i)
    {
        tA = iteration_verA(tA);
        tB = iteration_verB(tB);
        var approxA = 12 * Math.pow(2, i) * tA;
        var approxB = 12 * Math.pow(2, i) * tB;
        document.write("<tr><td>" + i + "</td>");
        document.write("<td>" + approxA + "</td>");
        document.write("<td>" + approxB + "</td></tr>");
    }

    document.write("</table>");
}

calculate_pi();

iteration_verA()(版本A)和iteration_verB()(版本B)在数学上是等效的。所以他们的输出应该是一样的,对吧?

#  Using Version A    Using Version B 
0  3.215390309173475  3.215390309173473 
1  3.1596599420975097 3.1596599420975013 
2  3.146086215131467  3.1460862151314357 
3  3.1427145996455734 3.1427145996453696 
4  3.141873049979866  3.141873049979825 
5  3.141662747055068  3.1416627470568503 
6  3.1416101765995217 3.1416101766046913 
7  3.141597034323337  3.1415970343215282 
8  3.141593748816856  3.1415937487713545 
9  3.141592927873633  3.1415929273850986 
10 3.1415927256225915 3.1415927220386157 
11 3.141592671741545  3.141592670702 
12 3.1415926189008862 3.141592657867846 
13 3.141592671741545  3.1415926546593082 
14 3.141591935881973  3.141592653857174 
15 3.141592671741545  3.14159265365664 
16 3.141581007579364  3.141592653606507 
17 3.141592671741545  3.1415926535939737 
18 3.1414061547376217 3.1415926535908403 
19 3.1405434924010995 3.141592653590057 
20 3.1400068646909682 3.1415926535898615 
21 3.1349453756588516 3.1415926535898126 
22 3.1400068646909682 3.1415926535898 
23 3.224515243534819  3.1415926535897975 
24 2.791117213058638  3.1415926535897966 
25 0                  3.1415926535897966 
26 NaN                3.1415926535897966 
27 NaN                3.1415926535897966 
28 NaN                3.1415926535897966 
29 NaN                3.1415926535897966

After 30 iterations using version B: 3.1415926535897966
Actual Value:                        3.1415926535897932384626433832795028841971...

显然,版本B工作并且给出了非常好的pi近似值(大约0.000000000000001%错误),而版本A甚至没有收敛!这是因为版本A容易出现数值错误,这种错误会在每次迭代时产生,而版本B在这种情况下会更加健壮。

对于任何进行任何严重数字运算的计算机程序来说,这当然是非常重要的。

答案 2 :(得分:2)

  

看起来在数学规则的现实中,它没有   无论是先加减还是减法。

不正确:   但是,如果您评估具有相同优先级的运算符的表达式,则表达式必须与从左到右计算它们的表达式相同。减法不是关联的。

关联性意味着事物x,y,x和运算符“$$”超过这些事物,x $$ y $$ z =(x $$ y)$$ z = x $$(y $$ z)< / p>

考虑:

1 - 1 + 1

正常评估:

(1 - 1)+ 1 = 0 + 1 = 1

从右到左的评估:

1 - (1 + 1)= 1 - 2 = -1

你有额外灵活性的原因是它是关联的,它允许你以任何方式攻击评估(当然如果你考虑 reflexivity 交换,你可以订购数字在任何方式的添加集合中)。你可能会感到困惑,因为从精神上来说,你可能并没有真正减去但是(做相当于)添加反转,在这种情况下,你正在弄乱的唯一二元运算符是。乘法/除法也会发生同样的事情。

现在,这是一个有趣的事实。添加浮点数不是关联的!

试试这两个:

Math.pow(10,100) + - Math.pow(10,100) + Math.pow(10,-100)

Math.pow(10,100) + (- Math.pow(10,100) + Math.pow(10,-100))

这两个数学应该评估为1e-100(Math.pow(10,-100)或1 x 10 -100 )....但他们没有。在第二种情况下,近似1×10 100 的巨大浮点数吞噬了1×10 -100 。浮点必须具有200个左右的精度数字(基数10)才能计算这两个数字。与其他运营商提出类似的例子可能有点棘手,但当然,通过反复试验,你可能会想出一些。重要的是要记住,浮点表达式的结果是近似,因此,您的结果不受数学规则的严格约束。

答案 3 :(得分:-1)

时间和除法在标准数学中的优先级高于加号和减号。如果javascript对+ - *和/具有相同的优先级,则会导致不同的结果。

5 + 6 * 7

可以是

(5 + 6) * 7

5 + (6 * 7)

数学做第二个,如果优先级相等而且它是左关联的,那么你得到第一个。