当前位置: 华文问答 > 数码

为什么在项目中要尽量避免使用浮点数,不使用浮点数,那该如何计算浮点数?

2017-10-02数码

「在项目中要尽量避免使用浮点数」本来就是个伪命题,很大程度上是以讹传讹得来的,比方说上面回答中那个猴子的故事就很形象。

这个以讹传讹的本体来源于工程需求,往往是要让人尽量用整数,却忽略了整数跟浮点同样都是有限精度。

如果你需要无限精度,那么只有自定义类型能满足。整数vs浮点并没有太大的优势。

实际上,浮点的误差来自十进制小数跟二进制小数之间的转换。如果这个转换对你具体的应用来说不是必须的,那么你就完全可以用浮点。

因而,不应该使用浮点数的常用场合只有一个,那就是:当你需要让一个变量精确的对应到现实中某个十进制小数时,不应当使用浮点小数来保存这个变量。当十进制小数与二进制浮点小数的转换不可避免,你又必须要求精度时,不应当使用浮点。

比方说 1.1 元钱,因为这个变量必须精确的等于十进制的 1.1,而变量本身是二进制,此时进制转换是必须的,所以你用浮点小数保存是错误的,你可以考虑用精确到分的 110 来表示这个数字,避免了小数。类似的,如果是计算器的话,如果用户是用十进制的格式输入,那么直接转换成二进制用计算机进行运算,最后再转换成十进制显示,这就不可避免的会有误差。

如果没有进制转换的需求,那么用浮点没有任何问题, 甚至不会有精确性方面的问题

那么举一些可以用浮点数例子:

1,如果你有一个只需要在计算过程中出现的变量,它的输入并不来源于十进制小数,也不需要被转换成十进制保存,那么它完全可以用浮点,最典型的就是游戏,你需要使用一个很复杂的增伤减伤公式来计算出实际的伤害,而这个伤害直接的被作用到了目标,在整个过程中,所有的操作都使用二进制进行,不存在二进制十进制转换,因此就不会产生误差,此时用浮点根本没有问题。——当然在游戏中,即便其中的变量最终需要以十进制显示,你仍然可以用浮点,因为十进制显示虽然有误差,但可以四舍五入显示,不需要绝对精确。

2,如果你的浮点仅仅用来存储精度内的整数,那么使用它也不会存在问题。例如 64 位浮点可以用来精确存储 2^47 以内的整数,不会存在任何误差。换句话说就是 64 位浮点可以无损的放进一个 32 位的 int,不存在任何误差,在 32 位整数不够用,系统又不支持 64 位整数时,它也可以被当作 47 位的整数类型使用。(47这个数字有争议,有说48,52,53等等的,但不影响具体结论,都大于32,装32位整数依然可以完全精确表示。)

同理,32 位的浮点则可以精确的放进一个 2^23 以内的整数,不存在任何误差。 32 位浮点变量保存一个 16 位的 short 类型整数不产生任何误差,它也可以被当作一个精度在 23 bit 的整数类型。

3,可能存在的其他例子,欢迎补充。

--

补充,其实有一个不应该使用浮点的不常用场合,就是目标cpu没有浮点处理器,此时的浮点使用整数模拟计算出,效率极低。鉴于现代的绝大多数大多数CPU都配备了浮点处理器,浮点运算的性能跟整数是相当的。如果使用现代的cpu,需要避免浮点的情况发生概率很小。但在一二十年前,有很多cpu(尤其是嵌入式cpu)还没有配备浮点处理器,此时确实应该尽量避免,甚至完全避免用浮点。