提问人:Bri Bri 提问时间:9/16/2018 最后编辑:Hadi BraisBri Bri 更新时间:9/16/2018 访问量:167
在同一台机器上运行时,C 程序的浮点精度在过去两周内发生了变化
Floating point [in]accuracy of C program, when running on the same machine, changed over last two weeks
问:
以下 C 代码今天在两个使用 Microsoft 编译器(随 Visual Studio 2017 社区一起安装)的系统上编译,这两个系统都具有现代 64 位 Intel 处理器并运行 Windows 10:
#include <math.h>
#include <stdio.h>
int main() {
int a = 64, b = 2;
double logA = log(a);
double logB = log(b);
double c = logA / logB;
printf("logA: %0.20lf\n", logA);
printf("logB: %0.20lf\n", logB);
printf("c: %0.20lf\n", c);
printf("result: %d\n", ((int)c));
return 0;
}
我们称它们为“系统 A”和“系统 B”,以保持清晰。两个系统打印的 和 的值完全相同:logA
logB
logA: 4.15888308335967149532
logB: 0.69314718055994528623
但是,对于和系统 A 打印:c
result
c: 6.00000000000000000000
result: 6
...系统 B 打印:
c: 5.999999999999...
result: 5
(我不再有它产生的确切结果,但足以说它比 6.0 略小。
我尝试在其他几个系统上编译相同的代码,包括运行 Windows 7 和 VS Community 2013 的旧系统以及运行 macOS 10.12 和 Xcode 9.3.1 的 mac,它们的结果与系统 A 一致,而不是系统 B。
这是它变得非常奇怪的地方:
更令人困惑的是,两周前在系统 B 上编译程序时,它产生了与系统 A 相同的结果!在此期间发生了一些变化,导致编译的程序产生不同的答案。
我的问题是:这到底是怎么发生的?!
我知道浮点不准确,并没有试图证明或原谅将结果除以和不四舍五入或以其他方式解释不准确的错误。这显然是一个错误。log(a)
log(b)
但是这个特殊的错误只在最近两周才显现出来,而且只在一个系统上。我无法在其他任何地方重现它。
据我所知,双精度浮点数学的结果是基于 CPU,而不是操作系统、编译器、C 运行时或任何其他软件。
为什么两周前生成 6.00000000000
的系统会突然切换到生成 5.9999999999?
(当然,Windows 10 喜欢自动静默更新自己,但系统 B 的所有者没有手动安装任何可以轻松解释此更改的更新。
为了我自己的教育和内心的平静,我真的很想知道这个问题的答案。
答: 暂无答案
评论
/fp:fast
log
mulsd
log
/fp:strict
/fp:precise
log
divsd
c
_BitScanForward64
转换为单个指令,而不是数百或数千个来计算对数。另请参阅计数位或查找最右边|最左边的位,graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious