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 的循环才对吧。

3644 次点击
所在节点    C
29 条回复
mm163
2018-10-14 10:19:07 +08:00
System.out.println((double)1-0.9)
ShuoHui
2018-10-14 10:19:18 +08:00
蜜汁节点,计算机二进制不能精确表示吧
zwh2698
2018-10-14 10:31:54 +08:00
有本书叫计算机组成与原理
Linyvhan
2018-10-14 10:33:02 +08:00
IEEE754
johnniang
2018-10-14 10:34:22 +08:00
说不定被编译器优化了
FrankFang128
2018-10-14 10:35:50 +08:00
你不能用十进制来思考这个问题
jiang1234321
2018-10-14 10:43:24 +08:00
@mm163 没啥区别啊,本身就会向高精度类型转换的
jiang1234321
2018-10-14 10:44:19 +08:00
@Linyvhan 这个知道,就是不知道为什么同样的 0.1,一个可以准确打印,一个不行,还有就是 0.333333333333333*3 怎么就等于 1 了
jiang1234321
2018-10-14 10:44:48 +08:00
@johnniang 能不能具体一点,或者给个文章什么的看一下,我觉得也是被编译器优化了,
will0404
2018-10-14 10:47:58 +08:00
同楼上,不能用十进制来思考计算机的基本运算。你需要补一下计算机基础。

就答最后一个问题,乘除操作在二进制层面是用移位和简单的加减实现的,不会有精度丢失(除非溢出),而精度是在转为十进制的时候丢失的,1.0/3.0*3.0 是先计算得到了 1.0 的二进制形式,它是可以准确用十进制表示的,当然不会得到 0.99999 …
ech0x
2018-10-14 10:48:22 +08:00
https://zh.wikipedia.org/zh-hans/浮点数
如果你真的要涉及到浮点数的输入输出,和不能有错的浮点数运算的话,请用 BigDecimal
will0404
2018-10-14 10:49:14 +08:00
建议你,CSAPP 第二章读一下。
liuminghao233
2018-10-14 10:51:04 +08:00
看 csapp 吧
SuperMild
2018-10-14 10:53:33 +08:00
建议趁此机会练习一下使用搜索引擎,这个问题网上有很多资料,从浅到深都有了,V 站上也是月经。
icyalala
2018-10-14 10:55:03 +08:00
可以仔细看一下 IEEE754 浮点数标准与计算过程。精度损失主要集中在这几个地方:
1. 大部分十进制表示的小数,是不能完全精确的由二进制的 IEEE 浮点数表示出来,编辑器解析字符串的过程中会有 rouding 过程。
2. 打印的时候,二进制大部分情况也不会完全用十进制表示出来,printf 会做舍入和截断。
3. 浮点数计算的过程中,可能会有精度损失。
可以在 https://www.exploringbinary.com/floating-point-converter/ 转换来看看。

"0.1" 解析后是 0x1.999999999999ap-4
"0.9" 解析后是 0x1.ccccccccccccdp-1 (注意最后一位)
1-0.9 得到的结果是 0x1.9999999999998p-4 (注意最后一位)

1.0 / 3.0 * 3.0 这三个数都能精确表示为 IEEE 浮点数
1.0 / 3.0 得到结果 0x1.5555555555555p-2
再乘以 3.0 得到结果 0x1p0
CEBBCAT
2018-10-14 12:02:09 +08:00
@icyalala 有博客吗?没 Google 到
pipapa
2018-10-14 12:12:19 +08:00
《深入理解计算机系统》第二章,自己转成二进制手动计算一下就知道了
VDimos
2018-10-14 13:44:05 +08:00
浮点的问题就和怎么退出 vim 一样,让无数新手疑惑
otakustay
2018-10-14 14:01:21 +08:00
摘一段说明得很详细的:



来源: http://math.ecnu.edu.cn/~jypan/Teaching/Cpp/doc/IEEE_float.pdf
icyalala
2018-10-14 14:25:12 +08:00
@CEBBCAT https://www.exploringbinary.com/topics/ 见 "Correctly Rounded Decimal to Floating-Point Conversion" 这部分的文章。

CSAPP 可以作为基础知识来了解一下,精度究竟是如何损失的、损失结果是怎么样的,这部分就没有介绍了。

把字符串解析为 IEEE754 浮点数,是非常复杂的事情,vc、gcc、jdk 甚至 libc 的 strtod 都出现过 bug。
IEEE754 浮点数运算,又是另一个话题了。

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

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

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

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

© 2021 V2EX