This question already has answers here:
Closed 3 years ago.
Is floating point math broken?
(31个答案)
我正在尝试优化我正在编写的一段C代码,我注意到产品比部门快得多。这是一个众所周知的问题,到处都有很好的解释。
考虑到这个优化,考虑到我一次又一次地除以同一个数,我试图计算这个数的逆,然后再乘以它。然而,我注意到结果并不完全相同。
我设法写了一个非常简单的例子,在这个例子中,我所说的区别是显而易见的:
#include <stdio.h>

int main(){
    double D = 1.1891;
    double Dinv = 1./D;

    double a = 23123.1234;
    double b = 156.123871;

    printf("1/D    = %.60f\n", 1./D);
    printf("Dinv   = %.60f\n", Dinv);
    printf("1/D == Dinv? %s\n\n", 1./D == Dinv ? "True" : "False");

    printf("a/D    = %.60f\n", a/D);
    printf("a*Dinv = %.60f\n\n", a*Dinv);
    printf("a/D == a*Dinv? %s\n\n", a/D == a*Dinv ? "True" : "False");

    printf("b/D    = %.60f\n", b/D);
    printf("b*Dinv = %.60f\n\n", b*Dinv);
    printf("b/D == b*Dinv? %s\n\n", b/D == b*Dinv ? "True" : "False");
}

如您所见,我测试a/D是否等于a*Dinv,其中Dinv = 1/D,并使用b进行相同的测试。此代码在我的机器中的输出如下:
1/D    = 0.840972163821377516335076052200747653841972351074218750000000
Dinv   = 0.840972163821377516335076052200747653841972351074218750000000
1/D == Dinv? True

a/D    = 19445.903120006725657731294631958007812500000000000000000000000000
a*Dinv = 19445.903120006729295710101723670959472656250000000000000000000000

a/D == a*Dinv? False

b/D    = 131.295829619039608360253623686730861663818359375000000000000000
b*Dinv = 131.295829619039608360253623686730861663818359375000000000000000
b/D == b*Dinv? True

正如您在输出中看到的,测试结果是不同的:我们可以看到a/D不等于a*Dinv,但是b/Db*Dinv完全相同。这种行为随着测试的数字而改变(ab不是我真正感兴趣的数字,它们只是我测试的示例)。我的问题是:
为什么a/Da*Dinv不同?
为什么有些数字通过了测试,而另一些不通过呢?
我们能谈谈准确度吗?我的意思是,给定a/Da*Dinv,我们能说其中任何一个比另一个更准确吗?
谢谢您!

最佳答案

为了部分地回答这个问题,a/Da*Dinv的结果可能不同,因为在a*Dinv中,即a*(1.0f/D),涉及一个额外的操作,这可能导致精度的损失。

关于c - 逆的除法和乘积的准确性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39145864/

10-14 01:38