C关联中的浮点操作?

加法数学上保持关联属性:

(a + b) + c = a + (b + c)

在一般情况下,该属性不适用于浮点数,因为它们以有限精度表示值。

作为优化的一部分,是否允许编译器在从C程序生成机器代码时进行上述替换? C标准究竟在哪里说的?


编译器不允许执行“优化”,这会导致计算出不同的值,而不是根据抽象机器语义计算的值。

5.1.2.3程序执行

[#1]本国际标准中的语义描述描述了优化问题无关的抽象机器的行为。

[#3]在抽象机器中,所有表达式都按照语义指定的方式进行评估。

[#13]示例5由于精度和范围的限制,浮点表达式的重新排列通常受到限制。 由于四舍五入误差,即使在没有上溢和下溢的情况下,实现通常不能将数学关联规则应用于加法或乘法,也不能应用分配规则。

在你的例子中:

(a + b) + c

甚至没有括号:

a + b + c

我们有

   +
  / 
  +  c
 / 
 a  b

并且需要编译器生成代码,就好像ab相加并且结果与c相加。


C中的浮点乘法不是关联的。

In C, Floating point multiplication is not associative.

这个C代码有一些证据:

选择三个随机浮点值。
检查a*(b*c)是否不等于(a*b)*c

#include<stdio.h>
#include<time.h>
#include<stdlib.h>
using namespace std;
int main() {
    int counter = 0;
    srand(time(NULL));
    while(counter++ < 10){
        float a = rand() / 100000;
        float b = rand() / 100000;
        float c = rand() / 100000;

        if (a*(b*c) != (a*b)*c){
            printf("Not equaln");
        }
    }
    printf("DONE");
    return 0;
}

该程序打印:

Not equal
Not equal
Not equal
Not equal
DONE
RUN FINISHED; exit value 0; real time: 10ms; user: 0ms; system: 0ms

结论:

对于我的测试,三个随机选择的浮点乘法值大约70%的时间是关联的。

链接地址: http://www.djcxy.com/p/15029.html

上一篇: Are floating point operations in C associative?

下一篇: How could I optimize this calculation ? (x^a + y^a +z^a)^(1/a)