为什么浮点数在不同平台/编译器会产生不一致性?

您所在的位置:网站首页 编译器使用 为什么浮点数在不同平台/编译器会产生不一致性?

为什么浮点数在不同平台/编译器会产生不一致性?

2023-04-02 13:55| 来源: 网络整理| 查看: 265

首先,按照浮点数的规范 IEEE 754 来的话,一致性是有保证的,并没有问题。

但浮点数总是有误差的,内部使用二进制表示,无法明确表达分数分母不是二的整数次幂的小数部分。因此,定点数在正确性方面是有优势的。定点数的计算一般也更快。

真正需要浮点数的是数值计算类的场合,数字可能很大或很小,不要求完全精确,范围又超出了整数的表达范围(32 位的话,有符号整数的最大值是 2^{31} - 1,约 2 \times 10^9 ,而 float 则可以表达到约 3 \times 10^{38} )——这才是真正需要浮点数的场合。

反过来,整数够用的话,干吗用浮点数?

上面的回答是针对“在游戏开发领域,人们为了实现不同客户端的一致性,往往使用定点数来做计算”回答的,我不认为这是真正的理由。

如果仅仅问为什么浮点数计算结果有区别,那是因为在你没有追求一致性的场合下,有些实现上的细节可以导致浮点数计算行为的变化:

浮点数在默认进行计算时编译器是不敢调整顺序的,但如果你不看重一致性,而更看重性能,那在 MSVC 下可以使用 /fp:fast 选项,在 GCC/Clang 下可以使用 -Ofast 选项,来让编译器为性能而放弃一致性。float 在一般的系统里都是 32 位,double 在一般的系统里都是 64 位。但 long double 在 MSVC 下是 8 位,在 GCC/Clang 下是 16 位。x86 上的浮点运算单元 x87 内部是 80 位,因此使用 x87 和不使用 x87(包括其他平台体系)计算结果可能不同。如果追求一致性,可以把 x87 的计算精度也设成 64 位(一般情况大家不会这么做)。如果编译器认为你的系统可以使用 SSE 之类的指令的话,计算精度又和 x87 不一样了。x87 有控制寄存器,可以修改一些行为,如舍入的方向和上面说的计算精度。设置不同,也有不一样的结果。

定点数的行为就好控制多了,没有这么多奇怪的细节。(不过,真正追求计算精度和一致性的场合,这些变量是可以控制的。如在科学计算里,一般就需要追求这种计算结果的一致性。)



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3