BigDecimal精确计算及陷阱

BigDecimal通常在涉及到精确计算的时候会用到,下面是自己多次错误使用BigDecimal的总结。

结论:

  1. BigDecimal初始化小数时,尽量用字符串形式,例如new BigDecimal("0.1");
  2. BigDecimal类型变量比较大小时用compareTo方法,判断变量值是否为0,与BigDecimal.ZERO比较大小。
  3. BigDecimal作除法时,除了要考虑除数是否为0,更要考虑是否能除尽的问题,直接调用BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)方法做除法可以避免除不尽的问题。

初始化BigDecimal变量:

//BigDecimal初始化
public static void testBigDecimalinit() {
    BigDecimal num1 = new BigDecimal(0.1);
    System.out.println("坑点1:num1="+num1);//坑点1:num1=0.1000000000000000055511151231257827021181583404541015625  

    BigDecimal num2 = new BigDecimal("0.1");
    System.out.println("正确写法:num2="+num2);//正确写法:num2=0.1
}   

结论:尽量用字符串的形式初始化,因为小数在计算机内部根本没法精确表示。

比较大小

比较BigDecimal类型的变量和0的大小,用compareTo,不要用equals:

if (num1.compareTo(BigDecimal.ZERO)>0)
if (num1.compareTo(BigDecimal.ZERO)<0)
if (num1.compareTo(BigDecimal.ZERO)==0) 
//比较大小
public static void testBigDecimalCompareTo() {
    BigDecimal num1 = new BigDecimal("0.1");
    BigDecimal num2 = new BigDecimal("0.100");  

    if (!num1.equals(num2)) {
        System.out.println("坑点1,用equals比较大小,num1="+num1+", num2="+num2+" 【不相等】");
    }
    if (!(num1 == num2)) {
        System.out.println("坑点2,用==运算符比较大小,num1="+num1+", num2="+num2+" 【不相等】");
    }  

    if (num1.compareTo(num2) == 0) {
        System.out.println("正确比较大小,用compareTo,num1="+num1+", num2="+num2+" 【相等】");
    }
}    

结论:比较大小或者值是否相等,用compareTo方法

BigDecimal除法

在出现除不尽的时候,会出现问题,例如1/3的问题:

//BigDecimal除法
    public static void testBigDecimalDivide() {
        BigDecimal num1 = new BigDecimal("1");
        //坑点:Exception in thread "main" java.lang.ArithmeticException: Non-terminating decima    l expansion; no exact representable decimal result.
//        System.out.println("坑点写法1:"+num1.divide(new BigDecimal("3")));
//        System.out.println("坑点写法2:"+num1.divide(new BigDecimal("3")).setScale(2, BigDecimal.ROUND_DOWN));  

        System.out.println("正确写法:"+num1.divide(new BigDecimal("3"), 2, BigDecimal.ROUND_HALF_DOWN));
    }    

结论:只有在divide的时候就设置好要精确的小数位数和舍入模式,才能避免出现无法精确表达除不尽的问题。

时间: 2024-07-29 21:30:08

BigDecimal精确计算及陷阱的相关文章

精确计算工具类,提供加减乘除的计算

package com.ljq.util; import java.math.BigDecimal; /** * 精确计算工具类,提供加减乘除的计算 * * @author jqlin */ public class CompuUtils { /**小数点后保留的位数*/ public final static int SCALE = 5; /** 0 */ public final static int ZERO = 0; /** * BigDecimal大小比较 * * @param a *

Java使用BigDecimal解决精确计算的问题

最近有人在微信上给我发了一个数学题目,如下图: 我看了之后感觉很是简单,但是却想了半天才解出来.解出来后我想到了用程序再解一遍,然而精确计算的问题却让人头疼不已. 解题思路: 思路其实很简单,暴力求解就可以,但是当你写了一个四重for循环后你会发现解不出来.由此考虑到结果可能是小数,便把增量改成了float类型,每次自增0.1. 当你写完满心欢喜地运行的时候会发现还是出不来结果.再改成double类型也同样是不行. 这是因为java中float类型相加是把十进制转化为二进制后相加然后把二进制结果

java精确计算之BigDecimal

Java中的计算主要有double,float,int,long,BigDecimal 1.float和double主要用户科学计算和工程计算,它们执行二进制浮点运算,这是为了在广泛的数值范围上提供较为精确的快速近似计算而设计的.然而它们并没有提供完全精确的结果,所以不应该被用于需要精确计算的场合. eg: double double_price1 = 1.03;  double double_price2 = 0.42;  System.out.println("double的计算值:&quo

JAVA中精确计算金额BigDecimal

package com.chauvet.utils; import java.math.BigDecimal;import java.text.DecimalFormat;import java.text.NumberFormat; /*** * * 金额 * * 如果需要精确计算,必须用String来够造BigDecimal! !! * * Java里面的商业计算,不能用float和double,因为他们无法 进行精确计算. * 但是Java的设计者给编程人员提供了一个很有用的类BigDeci

第二章 Java浮点数精确计算

1.实际意义 在实际开发中,如果需要进行float或double的精确计算(尤其是财务计算),直接使用float或double是不行的(具体的例子看下边的代码的main方法的测试结果),需要使用BigDecimal. 2.代码 package com.xxx.util; import java.math.BigDecimal; /** * 浮点数精准算法 */ public class BigDecimalArithUtil { private static final int DIV_SCAL

Java中浮点型数据Float和Double进行精确计算的问题

一.浮点计算中发生精度丢失  大概很多有编程经验的朋友都对这个问题不陌生了:无论你使用的是什么编程语言,在使用浮点型数据进行精确计算时,你都有可能遇到计算结果出错的情况.来看下面的例子. // 这是一个利用浮点型数据进行精确计算时结果出错的例子,使用Java编写,有所省略. double a = (1.2 - 0.4) / 0.1;System.out.println(a); 如果你认为这个程序的输出结果是“8”的话,那你就错了.实际上,程序的输出结果是“7.999999999999999”.好

Java浮点数float和double精确计算的精度误差问题总结

1.float整数计算误差 案例:会员积分字段采用float类型,导致计算会员积分时,7位整数的数据计算结果出现误差. 原因:超出float精度范围,无法精确计算. float和double的精度是由尾数的位数来决定的.浮点数在内存中是按科学计数法来存储的,其整数部分始终是一个隐含着的“1”,由于它是不变的,故不能对精度造成影响. float:2^23 = 8388608,一共七位,这意味着最多能有7位有效数字,但绝对能保证的为6位,也即float的精度为6~7位有效数字: double:2^5

BigDecimal精度计算

System.out.println(0.05+0.01); System.out.println(1.0-0.42); System.out.println(4.015*100); System.out.println(123.3/100); 上面的代码输出结果为 0.0600000000000000050.5800000000000001401.499999999999941.2329999999999999 原因在于我们的计算机是二进制的.浮点数没有办法是用二进制进行精确表示.我们的CPU

Java精确计算

Java精确计算 如果我们编译运行下面这个程序会看到什么? public class Test{ public static void main(String args[]){ System.out.println(0.05+0.01); System.out.println(1.0-0.42); System.out.println(4.015*100); System.out.println(123.3/100); } } 你没有看错!结果确实是 0.060000000000000005 0