運算符的優先順序、結合性、求值次序,新舊規則比較的解釋有點看不懂,求解釋?

英文版:

The precedence and associativity of operators is fully specified, but the order of evaluation of expressions is, with certain exceptions,undefined, even if the subexpressions involve side effects. That is, unless the definition of an operator guarantees that its operands are evaluated in a particular order, the implementation is free to evaluate operands in any order, or even to interleave their evaluation. However, each operator combines the values produced by its operands in a way compatible with the parsing of the expression in which it appears.

This rule revokes the previous freedom to reorder expressions with operators that are mathematically commutative and associative. but can fail to be computationally associative. The change affects only floating-point computations near the limits of their accuracy, and situations where overflow is possible.

中文版:

運算符的優先順序和結合性有明確的規定,但是,除少數例外情況外,表達式的求值次序沒有定義,甚至某些有副作用的子表達式也沒有定義。也就是說,除非運算符的定義保證了其操作數按某一特定順序求值,否則,具體的實現可以自由選擇任一求值次序,甚至可以交換求值次序。但是,每個運算符將其操作數生成的值結合起來的方式與表達式的語法分析方式是兼容的。

該規則廢除了原先的一個規則,即:當表達式中的運算符在數學上滿足交換律和結合律時,可以對表達式重新排序,但是,在計算時可能會不滿足結合律。這個改變僅影響浮點數在接近其精度限制時的計算以及可能發生溢出的情況。

求解答:

1、書中說,新規則廢除了原先的老規則,「表達式中的運算符滿足結合律和交換律時可以自由地對表達式重新排序」。後面又添加了一句「可能無法在計算時滿足結合律」。為什麼計算時可能無法滿足結合律?

2、規則的改變影響了「浮點數在接近其精度限制時的計算」和「可能發生溢出的情況」,求例子。


搜 浮點數 加法 結合律

&>&>&> 1e20
1e+20
&>&>&> -1e20
-1e+20
&>&>&> -1e20+1e20
0.0
&>&>&> -1e20+1e20+1
1.0
&>&>&> -1e20+(1e20+1)
0.0
&>&>&>


多年前看過一本c語言的書就記住了一句話的大概:不要去研究優先順序,上括弧。用括弧定義你需要的優先順序


首先我聲明,題主的問題我不確切知道。

但是可以隱約猜個大概。

如果是1+2+3,那麼結合律說白了就是(1+2)+3=1+(2+3)嘛

在浮點數計算精度限制或者溢出的時候,這種順序的交換會造成某些影響,導致結果不對。(浮點數運算我不熟)

題外話,我是看到操作符優先順序的問題進來的。

不知道題主研究這個問題的目的是什麼,但是從應用的角度來講,利用操作符的優先順序來寫邏輯的基本可以認為是爛代碼。(除非有相當確切的證據證明有巨大的性能提升)

所以,我個人認為這個東西可以忽略不計。

純屬路過。


看CSAPP學習了下新姿勢,我的問題就是看書想太多,看書效率低,導致看書太少,哎!

1.重排序表達式,因浮點數在接近精度限制時的計算造成的誤差,-1e100 + 1e100 + 1本來會得到1,重排後1e100+1+(-1e100)結果為0。

2.重排表達式導致發生溢出,(1e20*1e-20)*1e20的值為1e20,而1e20*1e20*1e-20將得出+∞;1e20*(1e20-1e20)的值為0.0,而le20*le20-le20*le20會得出NaN

所以浮點數在加法上不滿足結合律,浮點數乘法在加法上不滿足分配律。

新規則廢除了 當表達式中的運算符在數學上滿足交換律和結合律時,可以對表達式重新排序 的老規則,杜絕了某些編譯器因重排表達式造成,浮點數在接近其精度限制時的計算時產生意想不到的誤差以及重排表達式後發生溢出的情況。



推薦閱讀:

Haskell中自頂向下的類型類實例導出
Redis深入之道:原理解析、場景使用以及視頻解讀
使用 ucontext 在 C 中實現簡易協程
用MSIL寫程序:寫個函數做加法

TAG:編程語言 | C編程語言 | 編譯原理 | CC | C語言入門 |