1,浮点数基本知识
Java 语言支持两种基本的浮点类型: float 和 double ,以及与它们对应的包装类 Float 和 Double 。它们都依据 IEEE 754 标准,该标准定义了32 位单精度和 64 位双精度两种浮点二进制小数标准。
IEEE 754 用科学记数法以底数为 2 的小数来表示浮点数。
- 32位单精度浮点数float,用 1 位表示数字的符号,用 8 位表示指数,用 23 位表示尾数,即小数部分,如2^23 = 8388608,一共七位,这意味着最多能有7位有效数字,但绝对能保证的为6位,也即float的精度为6~7位有效数字。
- 64位双精度浮点数double,用1 位表示数字的符号,用 11 位表示指数,用52 位表示尾数,即小数部分,如2^52 = 4503599627370496,一共16位,也即double的精度为15~16位。
- 作为有符号整数的指数可以有正负之分,也即决定了浮点数的取值范围。小数部分用二进制(底数 2)小数来表示,这意味着最高位对应着值 ?(2 -1),第二位对应着 ?(2 -2),依此类推。
IEEE 浮点值的格式如图 1 所示:
2,浮点数比较
在java中浮点型默认是double的,浮点数都要在计算机里转换进行二进制存储,这就涉及到数据精度。
例如,十进制小数0.9表示成二进制数为:1100100100100......后面部分将无限循环下去,很显然,小数的二进制表示有时是不可能精确的。比如double类型表示小数部分只有52位,当向后计算52位后基数还不为0,那后面的部分只能通过四舍五入得到一个近似值,此时就造成精度丢失。
所以,当浮点数进行比较时,由于浮点数的二进制表示本身就不准确,比较大小时就会出现错误。例如float f1 = 20014999f == float f2 = 20015000f。
因此,有个原则:
- 程序中应尽量避免浮点数的比较
- float、double类型的运算往往都不准确
3,BigDecimal
要想获得理想的结果,应该使用BigDecimal来获得更精确的计算。
在《Effective Java》这本书中也提到这个原则,float和double只能用来做科学计算或者是工程计算,在商业计算中我们要用java.math.BigDecimal
。
BigDecimal够造方法的参数类型有4种,其中的两个用BigInteger构造,另一个是用double构造,还有一个使用String构造。应该避免使用double构造BigDecimal,因为:有些数字用double根本无法精确表示,传给BigDecimal构造方法时就已经不精确了。
比如,new BigDecimal(0.1)
得到的值是0.1000000000000000055511151231257827021181583404541015625。使用new BigDecimal("0.1")
得到的值是0.1。因此,如果需要精确计算,用String构造BigDecimal,避免用double构造。
BigDecimal都是不可变的(immutable)的,在进行每一步运算时,都会产生一个新的对象,由于创建对象会引起开销,因此它们不适合于大量的数学运算,所以a.add(b);
虽然做了加法操作,但是a并没有保存加操作后的值,正确的用法应该是a=a.add(b)。
4,小数点位数保留
- String s=String.format("%.2f",d),表示保留小数点后任意两位小数,并且符合四舍五入的规则。
- DecimalFormat df = new DecimalFormat("0.00"),不管传入的任何值,均保留两位小数。
- DecimalFormat df = new DecimalFormat("#.##"),则保留小数点后面不为0的两位小数,这种写法不能保证保留2为小数,但能保证最后一位数不为0。
- double d = 1.000;
BigDecimal bd=new BigDecimal(d);
double d1=bd.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
System.out.println(d1);
输出结果:1.0
若double d=0,输出结果为0.0;
若double d=1.999,输出结果为2.0;
若double d=1.89,输出结果为1.89;
这种写法若小数点后均为零,则保留一位小数,并且有四舍五入的规则。
参考:
https://www.ibm.com/developerworks/cn/java/j-jtp0114/index.html
http://blog.csdn.net/ccecwg/article/details/22286873
http://www.cnblogs.com/chenfei0801/p/3672177.html
http://www.ituring.com.cn/article/216160
http://swiftlet.net/archives/798
//www.greatytc.com/p/00fff555986b