簡體   English   中英

C中的浮點運算是關聯的嗎?

[英]Are floating point operations in C associative?

添加在數學上保持關聯屬性:

(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相加。

您可以使浮點運算與gcc選項相關聯:

-funsafe-math-optimizations -O2

例:

double test (double a, double b, double c) {    
  return (a + b + c) * (a + (b + c));
}

這減少為:

double temp = a + (b + c);
return temp * temp;

類似地, (a + b + c) - (a + (b + c))減少到零,忽略了INFNAN的可能性。

如果我用-fassociative-math -O2編譯,我得到了奇怪的消息:

警告:-fassociative-math disabled; 其他選項優先

如果您不關心操作數的順序, -funsafe-math-optimizations可以提高速度,但如果操作數的順序很重要,它可能會導致精度損失,並且您可能會丟失NANINF結果。

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 equal\n");
        }
    }
    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%的時間內是關聯的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM