double 浮点类型的一些疑问

2018-10-14 10:14:16 +08:00
 jiang1234321

1、 System.out.println(0.1); 输出是 0.1

2、 System.out.println(1-0.9); 输出是 0.09999999999999998

为什么同样是 0.1,直接打印就 ok,经过计算后就会由于 double 的精度导致输出循环。

还有,

    double x = 1.0;
    double y = 3.0;
    double z = 3.0;

    System.out.println(x/y*z);

为什么输出的是 1 ?应该是 0.9999999999999999999 的循环才对吧。

3654 次点击
所在节点    C
29 条回复
CEBBCAT
2018-10-14 15:35:03 +08:00
@icyalala #20 我想要的是您的博客,想加个 RSS
huiyifyj
2018-10-14 15:45:48 +08:00
计算机组成与原理,IEEE754 规格化和浮点数运算这方面请认真读。
pythonee
2018-10-14 19:06:23 +08:00
好久没有在 V2EX 看到这类的技术问题了
limbo0
2018-10-15 01:16:05 +08:00
经典问题哈,就是 2 进制保存小数不像整数一样,记得是 x/2**n 这种除以 2 次幂的形式,会有精度问题,运算时会损失精度,就是你看到的样子
jiang1234321
2018-10-15 10:18:20 +08:00
@icyalala 万分感谢,还有问题就是,解析后是这些数字在内存当中实际存储的值吗?
那为什么一个数字直接打印没问题,计算得到的打印就会循环呢?就像是问题描述的那样。
wutiantong
2018-10-15 10:57:12 +08:00
@Linyvhan #4 已经给出了最本质的解答:IEEE754
@jiang1234321 楼主看了一眼后回复了一句“这个我知道”就选择无视继续反复他的“疑问”。

事实上,假如楼主真的知道 IEEE754 在讲什么,他就不应该还有这些疑问。
所以我建议楼主早日克服自己不求甚解的毛病。

附上 wiki page: https://en.wikipedia.org/wiki/IEEE_754
icyalala
2018-10-15 11:40:33 +08:00
@jiang1234321

0.1 和 0.9 用二进制表示的话,都是无限循环的,但内存中的 double 只有有限位数,所以要做截断并 rounding 到最近的一个二进制,这里损失了精度。

"0.1" 解析后是 0x1.999999999999ap-4
"0.9" 解析后是 0x1.ccccccccccccdp-1
"1" 解析后是 0x1p0
1-0.9 实际在内存中的计算是 0x1p0 - 0x1.ccccccccccccdp-1 = 0x1.9999999999998p-4

直接写的 0.1 和经过计算得到的 0.1 在内存中的数值不相同,相差 2 ulp。

0x1.999999999999ap-4 转换为十进制时,是 0.1000000000000000055511151231257827021181583404541015625,print 会截断到 0.10000000000000000,舍去结尾的 0,就是 0.1。

0x1.9999999999998p-4 转换为十进制时,是 0.09999999999999997779553950749686919152736663818359375,print 会截断到 0.09999999999999998。

上面的这些 0x 开头的数值是用 Hexadecimal 格式写的,等同于 double 在内存中的实际数据。
jiang1234321
2018-10-15 14:14:56 +08:00
@icyalala 感谢,解答了心中的疑惑。
jiang1234321
2018-10-15 14:16:33 +08:00
@wutiantong 实在是没有这个能力和时间去看一篇英文的文章了,不过还是要感谢你的不求甚解的警钟。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/497456

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX