为什么不简单地从左到右评估?有人可以解释优先级如何使代码更具可读性吗?对我来说,这似乎需要更多的思考和更多的错误可能性。爱因斯坦说:“一切都应该尽可能简单,但不能简单。” 我猜他不是程序员。
8 回答
因为在数学中,在任何计算机语言发明之前,都有运算符优先级,例如
2 + 5 * 3 = 17 (and not 21)
*
运算符的优先级不高于运算符的语言+
会产生混淆。
C++的另一个例子:
std::cout << 7 * 8 << std::endl;
如果*
运算符没有优先于<<
运算符,则不会编译:
std::cout << 7
将首先被评估,产生结果(具有将被打印std::cout
的副作用)7
- 那么人们会想要评估
std::cout * 8
哪个 - 除非有人定义了一个非常奇怪的运算符*
来将 an 乘以outputstream
一个整数 - 没有定义。
运算符优先级允许不必在“常识范围内”放置不必要的括号(尽管我同意在某些情况下人们会引入错误,因为他们不知道实际的优先级)
现在你可能会问:为什么数学有运算符优先级?这篇维基百科文章提到了一些历史事实和讨论论坛的链接。对我来说,一个重要的论点是在编写多项式时,例如
ax^2 + bx + c
如果没有运算符优先级,则必须将它们写为:
(a(x^2)) + (bx) + c
APL没有运算符优先级(括号除外);代码从右到左读取(如希伯来语或阿拉伯语)。也就是说,APL 是一种利基语言,这就是原因之一。正如其他答案已经指出的那样,大多数其他语言都模仿了长期建立的算术优先规则,在我看来,这反过来似乎源于典型用例(即现实世界的问题)如何用最少数量的括号。
优先级的目的不是让它更具可读性,它是为了(a)标准化和(b)遵守数学中设定的标准,例如 PEMDAS。
存在运算符优先级的原因是因为您应该将总和2*4
视为整数。
所以你可以用一种2*4
不存在的方式来思考它。简直了8
。
所以你基本上在做的是“简化”总和,比如:2+10*2
这基本上是说:2+20
。
如以下总和:2143+8^2+6^9
. 你不想写出来2143+262144+10077696
。(想象一下,如果你有一个更大的公式,这会是什么样子)
基本上是为了简化总和的外观。加法和减法都是最基本的运算形式。所以这就是为什么有一个优先级,它是为了增加总和的可读性。
就像我说的,由于+
and-
运算符是最基本的运算符,那么首先解决更“复杂”的运算符是有意义的。
正如APL所展示的那样,可以取消优先规则——或者更准确地说,只有一个这样的规则。
“它只有一个简单、一致且递归的优先规则:函数的正确参数是该函数右侧的整个表达式的结果。”
例如,在“J”(APL 变体)中:
1+2*3 => 7 Computed as 1+(2*3)
2*3+1 => 8 Computed as 2*(3+1)
APL(和 J)有这么多运算符,很难记住每个运算符的优先级和关联性规则。
数字世界只是遵循老派“真实”世界的BEDMAS
规则:括号、指数、除法、乘法、加法、减法。
最好跟随现实世界,而不是试图重新定义现实并最终让程序员做
1 + 2 * 3
作为
(1 + 2) * 3 = 9
与现实世界的人相比
1 + (2 * 3) = 7
并将您的数百万美元的调查发送到无效的大气下降剖面,因为有人“带错了 1”。
例如,使用运算符优先级,以下计算结果为14:
2 + 3 * 4
没有它会评估为20,这是出乎意料的,恕我直言。
举个例子,如果没有运算符优先级,您将如何评估此表达式:
1+2/3
好吧,有些人会说你想将总和1+2
除以3
。其他你想添加2/3
的1
!