写点什么

《零基础学 Java》 FAQ 之 3- 为什么计算机里的浮点数不精确

用户头像
臧萌
关注
发布于: 2020 年 05 月 10 日
《零基础学 Java》 FAQ 之 3-为什么计算机里的浮点数不精确

用计算机的有限 PK 小数的无限



首先一个事实是,计算机是用固定的字节数来表示一个浮点数的。我们就拿double来举例,一个 double 变量占用8个字节,和整数的 long 是一样的。



但是小数的可能性有多少呢?从0.1到0.2,就有无数个小数。所以,浮点数不可能完全精确的表示小数。



在这里我大概说一下计算机是如何让处理小数的。怎么用有限的存储,表示无限的小数呢?原理很简单,就是舍弃精度。



比如说(没有写程序验证,只是从道理上说)对于从6.0000000000000001到6.0000000000000008的小数,计算机是用同一个二进制的数字来表示的,同时,计算和显示也都是用6.0000000000000001。这样就相当于舍弃了精度,让浮点数可以“近似的”表示很大范围内的浮点数。



当然,如果我们要表示整数部分很大的数字,比如123456789987654321.000009,那么精度将会变得更低。



所以大家理解为什么叫做浮点数了吗?因为浮点数的这个点,是指小数点;浮,是指这个小数点会浮动。如果整数部分过大,那么小数点后面的位数和精度就会变小。舍弃小数精度,让值更接近像表示的值。



其实浮点数在计算机里,是一个大学问。最开始PC上的CPU,是不能从硬件层面支持浮点数计算的,都要靠软件模拟,速度非常慢。当时牛X的PC,会带一个浮点数的协处理器,专门用来从硬件层面支持浮点数的运算。如果想深入了解为什么浮点数这么复杂,请参考下文:



What Every Computer Scientist Should Know About Floating-Point Arithmetic



浮点数不精确的例子



浮点数的精度涉及到浮点数本身的表示形式,理解起来还是略复杂的。简化版大概可以这么理解,在浮点数的世界里,一个具体的二进制的数字,其实表示的是一个范围,比如说下面的三行代码:



System.out.println(Double.toHexString(0.00000000000000000000000000000000000100000000000000021));
System.out.println(Double.toHexString(0.00000000000000000000000000000000000100000000000000022));
System.out.println(Double.toHexString(0.00000000000000000000000000000000000100000000000000032));



它们的输出是一样的



```

0x1.54484932d2e74p-120

0x1.54484932d2e74p-120

0x1.54484932d2e74p-120

````



这个意思是这三个数字,转换成浮点数的二进制后其实是一样的。这就是浮点数的精度的直观感受——非常相近的数字,二进制的表示形式是一样的。



就好像电子的轨道一样,不是说电子可以在任意轨道绕着原子核旋转,或者跃迁,光电效应了解一下?电子的轨道只能在固定的满足某个条件的轨道转圈。计算机也一样,不能表示无限精度的数字,只能尽力……

``System.out.println(0.00000000000000000000000000000000000100000000000000032 == 0.00000000000000000000000000000000000100000000000000022);``

比较也是一样的,正因为浮点数的这种不精确,导致其进行精确的比较是不可靠的,比如上面这两个不一样的数字,其实转换成二进制其实是一样的。输出的结果是true



同样的道理,这种不精确可能会积累,放大,所以浮点数的比较运算,比较推荐的是,求两个数字的差,然后让这个差取绝对值,和一个小到对业务没有影响的值比较,如果比这个值还小,就认为两个浮点数是相等的。






这篇文章来自极客时间推出的《零基础学Java》中的FAQ。除了在每节视频课下方回答大家的问题之外,针对大家提出的优质问题或者普遍问题,如果需要更大篇幅的文章解答,则会在FAQ中以文章的方式给出回答。带你零基础入门,夯实Java,课程地址:https://time.geekbang.org/course/intro/181



发布于: 2020 年 05 月 10 日阅读数: 62
用户头像

臧萌

关注

一线程序员,偶尔写写字 2017.10.20 加入

《零基础学 Java》,《职场求生攻略》 视频课作者 《Java入门1·2·3》作者

评论

发布
暂无评论
《零基础学 Java》 FAQ 之 3-为什么计算机里的浮点数不精确