java.math.BigDecimal

Posted ysyself

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java.math.BigDecimal相关的知识,希望对你有一定的参考价值。

public class BigDecimalDemo
 
    //1 没有无参构造方法, 如果没有参数,会直接编译错误。
 
 
    // 构造方法
    public static void testCon(double d1)
 
        BigDecimal b1 = new BigDecimal(d1);
        System.out.println("double参数的构造方法"+b1);
 
        //d1=2.01 的结果 :2.00 9999 9999 9999 9786 8371 7927 1969 9442 3866 271 9726 5625
        //显然存在一定的误差
        //所以这个方法不建议使用, 因为结果具有不可预知性,  具体原因可以参照文档解释。
   
 
    // 上面可修改为
    public static void testCon2(double d1)
        BigDecimal b1 = new BigDecimal(Double.toString(d1));
        System.out.println(b1);
   
    // 最好使用,通过String作为参数来构造
    public static void testString()
        BigDecimal b1 = new BigDecimal("2.111");
        System.out.println(b1);
   
 
    //静态工厂方法, 建议使用这个方法创建对象。内部存放着一些固定的对象, 可以直接使用
    //两个参数都可以为0 ,
    public static void testValueof(long unscaledVal, int scale)
        BigDecimal b1 = BigDecimal.valueOf(unscaledVal,scale);
        System.out.println(b1);
   
 
    // BigDecimal 转化为基本数据类型
    //转化都会导致数据丢失,不建议使用。
    public static void testXXXValue()
        BigDecimal b1 = new BigDecimal("89.1234567890123456789");
        //转化为双精度,有效位是16位。
        double d1 = b1.doubleValue();
        System.out.println("双精度:"+d1);  //双精度:89123.45678901234    刚好16位
 
        // 说明这样的转化, 丢失了数据的精度(准确度),另外其他的XXXXValue() 方法也是如此。 要慎重使用。
        // 那么问题来了 : 如何创建一个超过16位有效位数的数字呢? 我们都知道double 也才只有16位有效位数
        // 肯定不能作为BigDecimal参数的,
        // 所以这里只能用String类型的参数了。
 
   
 
    //精准加法运算
    public static void testAdd()
        BigDecimal b1 = new BigDecimal("22.22");
        BigDecimal b2 = new BigDecimal("22.2");
        b1 = b1.add(b2);
        System.out.println("加法:"+b1);   //加法:44.42 ,   说明: 标度值 Max(b1.scale,b2.cale) 去最大的那个。
   
 
    // 精准减法
    public static void testSubtract()
        BigDecimal b1 = new BigDecimal("22.22");
        BigDecimal b2 = new BigDecimal("22.2");
        b1 = b1.subtract(b2);
        System.out.println(b1);   //0.02   说明: 标度值 Max(b1.scale,b2.cale) 去最大的那个。
   
 
 
    // 乘法运算
    public static void testmultiply()
        BigDecimal b1 = new BigDecimal("22.22");
        BigDecimal b2 = new BigDecimal("0.02");
        b1 = b1.multiply(b2);
        System.out.println(b1); //0.4444   说明: 标度值scale = b1.scale+ b2.scale+ .....
 
   
    //除法
    public static void testDivide()
        BigDecimal b1 = new BigDecimal(1);
        BigDecimal b2 = new BigDecimal(3);
//        b1 = b1.divide(b2);        // 1/3当无法除尽时,会报错 ,因为没有提供舍入模式,和标度值
        System.out.println(b1);
   
    
    //精准除法
    public static void testDivide2()
        BigDecimal b1 = new BigDecimal(1);
        BigDecimal b2 = new BigDecimal(3);
        b1=b1.divide(b2,8,BigDecimal.ROUND_CEILING);  //向正无限大方向舍入的舍入模式, 标度为8
        System.out.println(b1);         //0.33333334
   
 
    //格式化
    //由于NumberFormat类的format()方法可以使用BigDecimal对象作为其参数,
    //可以利用BigDecimal对超出16位有效数字的货币值,百分值,以及一般数值进行格式化控制
    // 货币格式, 百分比
    public static void testFormat()
        BigDecimal b1 = new BigDecimal("12345678901244442.46666");
        BigDecimal b2 = new BigDecimal(100);
        BigDecimal b1In = b1.multiply(b2);
        //货币格式化引用
        NumberFormat  c = NumberFormat.getCurrencyInstance();
        //建立百分比引用
        NumberFormat p = NumberFormat.getPercentInstance();
        p.setMaximumFractionDigits(3);              //  设置百分比小数点最多3位数
 
        System.out.println("b1In:"+b1In);
        System.out.println("货币格式:"+c.format(b1));   //¥12,345,678,901,244,442.47 多次测试后小数点后面固定两位。
 
        System.out.println("百分比格式:"+p.format(b1));
 
 
   
 
 
    public static void main(String[] args)
 
//        testSubtract();
        testValueof(-1,1);
   
 
 


 

public static void main(String[] args)
    
        BigDecimal bigDecimal = new BigDecimal(2);
        BigDecimal bDouble = new BigDecimal(2.3);
        BigDecimal bString = new BigDecimal("2.3");
        System.out.println("bigDecimal=" + bigDecimal);//输出:bigDecimal=2
        System.out.println("bDouble=" + bDouble);//输出:bDouble=2.9999999
        System.out.println("bString=" + bString);//输出:bString=2.3
    

构造方法注意事项

参数类型为double的构造方法的结果有一定的不可预知性;String 构造方法是完全可预知的;所以我们在编写代码时尽量都用String 构造方法。当double必须用作BigDecimal的源时可以用BigDecimal的静态方法 valueOf() 如:

BigDecimal bDouble1 = BigDecimal.valueOf(2.3)

运算方法

public BigDecimal add(BigDecimal value);                        //加法

public BigDecimal subtract(BigDecimal value);                   //减法 

public BigDecimal multiply(BigDecimal value);                   //乘法

public BigDecimal divide(BigDecimal value);                     //除法

运算实例

public static void main(String[] args)
    
        BigDecimal a = new BigDecimal("4.5");
        BigDecimal b = new BigDecimal("1.5");

        System.out.println("a + b =" + a.add(b));
        System.out.println("a - b =" + a.subtract(b));
        System.out.println("a * b =" + a.multiply(b));
        System.out.println("a / b =" + a.divide(b));
    

运算注意事项

除法运算 divide() 方法,可能出现不能整除的情况,比如 4.5/1.3,这时会报错java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result。其实divide方法有可以传三个参数。

public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode) 

第一参数表示除数
第二个参数表示小数点后保留位数,
第三个参数表示舍入模式,只有在作除法运算或四舍五入时才用到舍入模式,具体舍入模式请查看,舍入模式章节。

舍入模式

 
ROUND_CEILING    //向正无穷方向舍入

ROUND_DOWN    //向零方向舍入

ROUND_FLOOR    //向负无穷方向舍入

ROUND_HALF_DOWN    //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向下舍入, 例如1.55 保留一位小数结果为1.5

ROUND_HALF_EVEN    //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,如果保留位数是奇数,使用ROUND_HALF_UP,如果是偶数,使用ROUND_HALF_DOWN

ROUND_HALF_UP    //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向上舍入, 1.55保留一位小数结果为1.6

ROUND_UNNECESSARY    //计算结果是精确的,不需要舍入模式

ROUND_UP    //向远离0的方向舍入

舍入实例方法

public static void main(String[] args)
    
        BigDecimal a = new BigDecimal("4.5635");

        a = a.setScale(3, RoundingMode.HALF_UP);    //保留3位小数,且四舍五入
        System.out.println(a);
    

以上是关于java.math.BigDecimal的主要内容,如果未能解决你的问题,请参考以下文章