随笔 - 1683  文章 - 618 评论 - 439 trackbacks - 0

有这样一道智力题:三人住旅馆,老板娘说30元她们付钱后进去了,老板娘想起今天是特价25元,就叫伙计拿5元还给三位顾客,可伙计藏了2元,给了她们3元,这样她们每人得1元,就是说每人付了9元,那3*9=27,再加伙计藏的2元,等于29元,那还有1元哪里去啦?

很多人疑惑蛮久,这剩下的1块钱到底去了哪里?我们用角色分析一下:

老板:实得到25元

伙计:实得 2元

客户:付出3*9=27成本

27=25+2 成本和收益是平衡的。上面主要是混淆了逻辑。

但在java开发中,你的钱也许一不小心就会丢失哦,请看题!

一块钱哪里去了?--java浮点型背后的故事

 

public class TestFloatDouble {
public static void main(String[] args) {
System.out.println(0.05f+0.01f);
System.out.println(1.0f-0.42f);
System.out.println(4.015d*100);
System.out.println(123.3d/100);
}
}

猜对话,有大奖!哈哈

0.060000002
0.58000004
401.49999999999994
1.2329999999999999

我们发现在使用浮点数类型float或者double进行运算时,数据有可能会失真。是上面原因呢?

我们知道,计算机并不能识别除了二进制数据以外的任何数据。无论我们使用何种编程语言,在何种编译环境下工作,都要先 把源程序翻译成二进制的机器码后才能被计算机识别。以上面提到的情况为例,我们来验证一下

public class TestFloatDouble {
public static void main(String[] args) {
System.out.println(Float.toHexString(0.05f));
System.out.println(Float.toHexString(0.01f));
System.out.println(Float.toHexString(1.0f));
System.out.println(Float.toHexString(0.42f));

System.out.println(Double.toHexString(4.015d));
System.out.println(Double.toHexString(123.3d));

System.out.println(0.05f+0.01f);
System.out.println(1.0f-0.42f);
System.out.println(4.015d*100);
System.out.println(123.3d/100);
}
}

其结果为:

0x1.47ae14p-7
0x1.0p0
0x1.ae147ap-2
0x1.00f5c28f5c28fp2
0x1.ed33333333333p6
0.060000002
0.58000004
401.49999999999994
1.2329999999999999

其中:ox表示十六进制

p表示指数,其基数是2

应该是不难理解的。

一块钱哪里去了?--java浮点型背后的故事

 

总之, 在需要精确答案的地方,要避免使用float 和double;对于货币计算,要使用int、long 或BigDecimal。

参考资料:

【1】https://blog.csdn.net/aya19880214/article/details/45891581

posted on 2019-09-01 14:10  一天不进步,就是退步  阅读(...)  评论(... 编辑 收藏