第⼆章Java浮点数精确计算
1、实际意义
在实际开发中,如果需要进⾏float或double的精确计算(尤其是财务计算),直接使⽤float或double是不⾏的(具体的例⼦看下边的代码的main⽅法的测试结果),需要使⽤BigDecimal。
2、代码
util;
import java.math.BigDecimal;
/**
* 浮点数精准算法
*/
public class BigDecimalArithUtil {
private static final int DIV_SCALE = 10;//除法精度(除不尽时保留10为⼩数)
/** ⼩数精确加法 */
public static double add(double d1,double d2)
{
BigDecimal bd1 = BigDecimal.valueOf(d1);
BigDecimal bd2 = BigDecimal.valueOf(d2);
return bd1.add(bd2).doubleValue();
}
/** ⼩数精确减法 */
public static double sub(double d1,double d2)
{
BigDecimal bd1 = BigDecimal.valueOf(d1);bigdecimal除法保留小数
BigDecimal bd2 = BigDecimal.valueOf(d2);
return bd1.subtract(bd2).doubleValue();
}
/** ⼩数精确乘法 */
public static double mul(double d1,double d2)
{
BigDecimal bd1 = BigDecimal.valueOf(d1);
BigDecimal bd2 = BigDecimal.valueOf(d2);
return bd1.multiply(bd2).doubleValue();
}
/** ⼩数精确除法 */
public static double div(double d1,double d2)
{
BigDecimal bd1 = BigDecimal.valueOf(d1);
BigDecimal bd2 = BigDecimal.valueOf(d2);
/*
* 当除不尽时,以四舍五⼊的⽅式(关于除不尽后的值的处理⽅式有很多种)保留⼩数点后10位⼩数
*/
return bd1.divide(bd2, DIV_SCALE, BigDecimal.ROUND_HALF_UP).doubleValue();
}
public static void main(String[] args)
{
/
/测试加法
System.out.println("0.05+0.01="+BigDecimalArithUtil.add(0.05,0.01));
System.out.println("0.05+0.01="+(0.05+0.01));
//测试减法
System.out.println("1.0-0.42="+BigDecimalArithUtil.sub(1.0,0.42));
System.out.println("1.0-0.42="+(1.0-0.42));
//测试乘法
System.out.println("4.015*100="+BigDecimalArithUtil.mul(4.015,100));
System.out.println("4.015*100="+(4.015*100));
//测试除法
System.out.println("123.3/100="+BigDecimalArithUtil.div(123.3,100));
System.out.println("123.3/100="+(123.3/100));
}
}
View Code
3、注意点
上边的程序我⽤的是BigDecimal.valueOf(double x)来将double型的x封装成BigDecimal,查看源码如下:
/**
* 注意:这通常是将double和float转换为⼀个BigDecimal的最好⽅式
*/
public static BigDecimal valueOf(double val) {
return new String(val));
}
View Code
在这⾥直接先将double转换为了String,然后使⽤如下构造⽅法再将String转换为BigDecimal
public BigDecimal(String val)
这是最好的做法。如果使⽤的是直接将double或float转换为BigDecimal的⽅式,也就是说使⽤的如下构造器,那么将可能得不到精确结果。(看注释)这⼀点可以⽤10.02*10.02来证明。
/**
* 注意:The results of this constructor can be somewhat unpredictable.
* 该构造器的结果有时是不准确的
*/
public BigDecimal(double val)
View Code
在实际使⽤中还可能使⽤int和long来进⾏浮点数的精确计算(具体做法:将浮点数先乘以相应的倍数转化为int(<=9位⼗进制数)或long(<=18位⼗进制数),计算之后再除以之前的倍数,得出结果),⽽且该种⽅式的性能会更⾼,具体的int、long和BigDecimal各⾃的使⽤看《Effective Java(第⼆版)》第48条。
需要指出的是,在实际开发中,BigDecimal的性能差的问题基本可以忽略,是浮点数精确计算的⾸选,⽽且根据上⼀条来看,如果将浮点数转化后的整数⼤于18位的话,也必须⽤BigDecimal
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论