找零程序出错的原因在于,1.1这个数字不能被精确的表示为一个double,因此被表示为最接近它的double值。改程序从2中减去的就是这个值。遗憾的是,这个计算的结果并不是最接近0.9的double值。作为结果的double值的最短表示就是你看到的那个程序输出的可恶的数字。
并不是所有的小数都可以用二进制浮点数精确表示。如果使用的是JDK5或者更新的版本,那么您可能会受其诱惑,通过使用printf工具设置输出精度的方法改正程序:
System.out.pringln("%.2f%n"2.00-1.10");
这条语句打印的结果正确,但并不表示它就是对底层问题的通用解决方案:它使用的仍旧是二进制浮点数的double运算。浮点运算在一个范围很广的值域上提供了很好的近似,但是通常不能产生精确的结果。二进制浮点对于货币计算是非常不合适的,因为它不可能将0.1或者10的其他任何次幂,精确的表示为一个有限长度的二进制小数。
解决该问题的一种方式就是使用某种整数类型。例如int或者long,并且以分为单位来执行计算。如果采纳了此路线,请确保改整数类型大到足以表示程序中将要用到的所有值。对该谜题来说,int就足够了。下面使用int类型,以分为单位表示货币值后重写的println语句:
System.out.println((200-190) + "cents");
解决改问题的另一个方式就是使用执行精确小数运算的BigDecimal。它还可以通过JDBC与SQLDECIMAL类型进行互操作。这里要注意一点:一定要用BigDecimal(String)构造器,而千万不要用BigDecimal(double)。后一个构造器将用他的参数的精确值来创建一个实例。例如new BigDecimal(.1),它将返回一个BigDecimal,也即0.100000000000000055511151231257827021181583404541015625.正确使用BigDecimal,程序就可以输出我们所需要的结果0.90:
import java.math.BigDecimal;
public class Change{
public static void main(String[] args){
System.out.println(new BigDecimal("2.00").subtract(new BigDecimal("1.10")));
}
}
在需要精确答案的地方,要避免使用float和double;对于货币运算,要使用int,long,BigDecimal。
分享到:
相关推荐
java中一些疑难问题的剖析,对初学java者有很好的帮助。
在JDK1.2中,Thread.stop、Thread.suspend以及其他许多线程相关的方法都因为它们不安全而不推荐使用了。下面的方法展示了你用Thread.stop可以实现的可怕事情之一
一本很好的java参考书,帮助你解决java中的很多注意不到的问题。
java解惑java解惑java解惑java解惑java解惑java解惑
java中最容易被忽略的地方. 博文链接:https://justjavac.iteye.com/blog/175252
这篇文档主要是介绍各种大家需要注意的java各种语法细节。希望对大家有所帮助。写的比较幽默。类似“十六进制的趣事”这种问题,估计在SSH大行其道的情况下,有些细节大家都不太关注了。
Java解惑Java解惑Java解惑Java解惑Java解惑Java解惑Java解惑Java解惑Java解惑Java解惑Java解惑Java解惑
表达式之谜,符号之谜,循环之谜,异常之谜,类之谜,库之谜,各种谜题。
《Java解惑》《Java解惑》《Java解惑》《Java解惑》《Java解惑》《Java解惑》
Java解惑.pdf Java解惑.pdf Java解惑.pdf Java解惑.pdf
比较容易混淆的java面试题,看看对笔试面试有一定的帮助。
Java解惑中文版 Java解惑 java健壮程序
JAVA解惑.pdf JAVA解惑.pdf JAVA解惑.pdf
与java相关的的学习,适合初学者,可以看看
java爱好者必备--JAVA解惑(中文版PDF)
Java PUZZLE Java 解惑 Java PUZZLE Java 解惑 Java PUZZLE Java 解惑Java PUZZLE Java 解惑 Java PUZZLE Java 解惑 Java PUZZLE Java 解惑
JAVA解惑,你面包括一些java经典的问题。
JAVA解惑(PDF) Java学习中所涉及到的一些疑难杂症。