找零时刻---浮点数计算

我们先来看一小段故事和解决该问题的代码.

Tom在一家汽车配件商店购买了一个价格为$1.10的火花塞,但是他的钱包里都是面额为两美元的钞票.当他用一张两美元的钞票来支付这个火花塞,那么销售员应该找给Tom多少零钱呢?

//下面是一段大家可能都会认可的代码

public class Test{
    public static void main(String[] args){
        System.out.println(2.00 - 1.10);
    }
}

/*你可能会天真地认为该程序代码能够实现,并且打印出正确结果0.90.
当然你的感觉是有一定道理的,如果你对Double.toString文档中设定的将double类型的值转换为String(字符串)的规则有点了解,你就会觉得该程序打印出来的小数是足以将double类型的值与最靠近它的临近值区分并打印出来的,它在小数点之前和之后都至少有一位.
*/

所以,你的直觉看起来还蛮有道理的~,
那么结果到底如何呢?如果你打印后就会发现它打印的是0.8999999999999999
这是为什么呢?
问题在于1.1这个数字并不能被精确的表示为一个double,它只能被表示最近它的double值.上面的代码就是试图从2中减去这个值,遗憾的是这个计算的结果并不是最接近的0.9的double值,所以打印出的就是你没想到的那个邪恶的值.

直接的说,并不是所有的小数都可以用二进制浮点数来精确表示.!

下面有几种解决的方案:

1,依旧使用二进制浮点数
2,使用整数类型,例如:int或long
3,使用执行精确小数运算的BigDecimal想了解~

下面就是用三种方式实现的代码(控制台有打印出的结果)
代码实现

但有一点就是,Java并没有为BigDecimal提供任何语言上的支持.所以大家可能稍微有些陌生.......

使用BigDecimal的计算很有可能比那些使用原始类型的计算要慢一些,对某些大量使用小数计算的程序来说,这可能会成为问题,而对大多数程序来说,这显得一点也不重要。

总之, 在需要精确答案的地方,要避免使用float和double;对于货币计算,要使用int、long或BigDecimal。对于语言设计者来说,应该考虑对小数运算提供语言支持。一种方式是提供对操作符重载的有限支持,以使得运算符可以被塑造为能够对数值引用类型起作用,例如BigDecimal。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值