您的位置:首页 > 编程语言 > Java开发

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

2016-11-26 22:19 344 查看
我们先来看一小段故事和解决该问题的代码.

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。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息