[英]What does computationally associative mean?
K&R的C語言有如下一句話:
編譯器將數學關聯運算符視為計算關聯運算符的許可已被撤銷。
這在附錄 C 中,它說明了與 ANSI C 之前的不同之處。但我不知道計算關聯與數學關聯有何不同。 也許我猜數學上的關聯是a * b * c = (a * b) * c (左)或a * (b * c) (右)。
考慮這段代碼:
#include <stdio.h>
int main(void)
{
double a = 0x1p64; // Two the power of 64, 18,446,744,073,709,551,616.
double b = 1;
double c = -a;
printf("%g\n", a+b+c);
}
在C語法中, a+b+c
等價於(a+b)+c
,所以先加上a
和b
,再加c
。 在double
常用的格式中, a+b
產生 2 64 ,而不是 2 64 +1,因為double
格式沒有足夠的精度來表示 2 64 +1,所以加法的結果是四舍五入到的理想數學結果最接近的可表示值,即 2 64 。 然后添加c
產生零,所以打印“0”。
相反,如果我們計算a+c+b
,將a
和c
將得到零,然后將b
相加得到一,並且將打印“1”。
因此,浮點運算通常不是關聯的; a+b+c
與a+c+b
不同。
在實數的普通數學中, a + b + c與a + c + b相同; 實數相加是結合的。
在標准化之前,一些 C 編譯器會將浮點表達式視為運算符是關聯的(對於那些在實數算術中對應的運算符是關聯的)。 C 標准不允許在符合該標准的實現中這樣做。 符合標准的編譯器必須產生結果,就好像操作是按照 C 語法指定的順序執行的一樣。
在非標准模式下運行時,某些編譯器可能仍將浮點運算符視為關聯運算符,這可能通過傳遞給編譯器的標志或開關來選擇。 此外,由於 C 標准允許實現以比標稱類型更精確的方式執行浮點運算(例如,在計算a+b+c
時,它可以將其計算為long double
而不是double
),這可以產生的結果與重新排列操作的結果相同,因此您仍然可以獲得看起來像操作符已關聯重新排序的結果,具體取決於 C 實現和使用的標志。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.