[英]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.