一、为什么想到这个问题
想到这个问题,主要是最近重读《Java核心技术:卷Ⅰ》
首先引用中的一段说明:
警告:浮点数值不适用于无法接受舍入误差的金融计算中。例如,命令System.out.println(2.0-1.1)将打印出0.8999999999999999,而不是人们想象的0.9。这种舍入误差的主要原因是浮点数值采用二进制系统表示,而在二进制系统中无法精确地表示分数1/10。这就好像十进制无法精确地表示分数1/3一样。如果在数值计算中不允许有任何舍入误差,就应该使用BigDecimal类。
最简单的示例,随便一个浏览器中按F12,选择控制台(有的叫Console),输入0.2+0.1,然后回车,看看会返回什么?
相信你99.99%会得出如下结果:(以防万一留下0.01%,(~ ̄▽ ̄)~):
> 0.2+0.1
< 0.30000000000000004
这是为什么呢?
二、关于这个问题的解释
在说二进制之前,先来看下十进制的10/3,下边是大家非常熟悉的数学竖式计算法:
上边的算式相信学过小学数学的同学都能明白,不过这是十进制的,也就是逢十进一,也就是所有的十进制数都是由0,1,2,3,4,5,6,7,8,9这十个数字组成的。
好了,下边来简单说一下二进制,相对于十进制来说,他是逢二进一,也就是所有的二进制只有0和1。
看一个例子:10代表的是十进制的二,11代表的是十进制的三,依此类推:十进制的十就是1010。
关于二进制更多的内容,可以查看相关书籍,这里就不再赘述了。
了解了二进制,则十进制的0.1用二进制的除法算式表示成 1/1010,看下边的除法算式:
相信你已经明白了,这和十进制的10/3一样,无线循环呀!!
通过上边两个除法算式的竖式形式,个人感觉就非常形象的揭示了为什么在计算机的二进制世界无法精确的表示0.1了。
三、扩展阅读
1、一篇文章:上边二进制的图就是截取自这篇文章,然后仿照它我画的十进制的竖式
2、一个网站:
Floating Point Mathhttps://0.30000000000000004.com/
光看这个网站名就非常有意思,它里边介绍了各种变成语言关于浮点数0.1之类的计算,可以了解一下,截几个比较大众的语言。
希望我的这篇笔记可以帮到你,也感谢三连支持的你!~ ─=≡Σ(((つ•̀ω•́)つ