java浮点精度总结

以前还真没这么在意过精度,这次因为要算数据,精确到万分之一,于是碰到了不少问题。

因为数据样本多,于是总有那么个不正常的。先举个例子

double preNum = 8;//6.4;
double curNum = 8.53;//5.56;
double r = curNum/preNum;
System.out.println("r="+r);

打印出 r=1.06625 没有问题。那么换成后面注释的一组数6.4和5.56,那么打印出来的是r=0.8687499999999999,按理应该是0.86875

于是问题产生了,如果保留4为小数,0.86875是0.8688,而0.86874999,保留下来是0.8687,差了0.1

为了解决这个0.1,我开始想办法了。

一、放大到整数

本来想把都放大到整数,但用这两组数试了试,不行。正好相反了,如

double avgnum  =  curNum*100000/preNum;
用8和8.53这组数,打印出来的是avgnum=106624.99999999999,另一组数正常了。


二、用BigDecimal

BigDecimal bPreNum = new  BigDecimal(preNum);
BigDecimal bCurNum = new  BigDecimal(curNum);
bCurNum.divide(bPreNum,6,BigDecimal.ROUND_HALF_UP).doubleValue();
结果还是有问题。都说这个精度高,我没看出高在哪里,仔细研究了研究,

换成

BigDecimal bPreNum = new  BigDecimal(preNum+"");
BigDecimal bCurNum = new  BigDecimal(curNum+"");
bCurNum.divide(bPreNum,8,BigDecimal.ROUND_HALF_UP).doubleValue();
没问题了,原来构造时用string精度能够保证。这里保留8位不是6位的原因是,例如0.6334495,这样保留6位是0.633450,在保留4位是0.6335,差了0.0001。


还剩下一组数忘了,碰到的是结果*100,也就是例如6.2356*100【因为忘了数据了,举个例子】,结果给我出来6.235599999,于是又用BigDecimal.

经过这次发现,如果要精度高点的,需要用到BigDecimal,不管乘除。

另外四舍五入的问题。

double ft = 98.425;
		java.text.DecimalFormat   df   =new   java.text.DecimalFormat("#0.00");
		String rtnf = df.format(ft);
		System.out.println("Format="+Double.valueOf(rtnf));
		System.out.println("big="+new BigDecimal(ft).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
		System.out.println("big_100="+new BigDecimal(ft*100).setScale(0, BigDecimal.ROUND_HALF_UP).doubleValue()/100);

打印出来结果是

Format=98.42
big=98.42
big_100=98.43


从这里可以看到,BigDecimal.ROUND_HALF_UP只对小数点后面一位数字有效。

上面的问题折腾了2天,总算搞明白各种差0.0001的原因。


java浮点精度总结,布布扣,bubuko.com

java浮点精度总结

上一篇:桶式排序与基数排序举例及JAVA代码实现(附:基数排序的方法给英文字符串排序)


下一篇:Java常见问题和解决办法