BigDecimal详解(附加减乘除等6大用法)

BigDecimal详解(附加减乘除等6大用法)-mikechen

Java程序员编程里经常会涉及货币金钱,这个时候BigDecimal就派上用场了,下面我就来详解BigDecimal@mikechen

什么是BigDecimal?

BigDecimal 是Java在java.math包中提供的API类,主要是用于金钱等要求高精度数值的计算。

Java 类中的 BigDecimal 提供算术运算(加、减、乘、除)、舍入、比较、散列和格式转换,BigDecimal 表示不可变的任意精度的有符号十进制数。

 

为什么需要BigDecimal?

前面学习Java8大基本类型的时候,我们可以使用float 和 double来表示浮点型数字,但是这里有一个问题那就是基本数据类型float 和 double不应该用于高精度数据的表示。

例如货币,因为浮点类型的float 和 double会丢失数据的精度。

举一个例子:

double d1 = 374.56;
double d2 = 374.26;
System.out.println( "d1 - d2 = " + ( d1 - d2 ));

这里本应输出的是0.30,但是实际上输出如下:

d1 - d2 = 0.30000000000001137

float和double类型尤其不适合用于货币运算,因为要让一个float或double精确的表示0.1或者10的任何其他负数次方值是不可能的。

其实道理很简单,十进制系统中能不能准确表示出1/3呢?同样二进制系统也无法准确表示1/10,浮点运算很少是精确的,只要是超过精度能表示的范围就会产生误差。

这就是为什么在金融相关的程序里数据类型如此重要的原因,所以我们更好的选择是BigDecimal 而不是float 和 double。

 

BigDecimal常用构造函数

1.创建一个具有参数所指定整数值的对象

BigDecimal(int)

2.创建一个具有参数所指定双精度值的对象

BigDecimal(double)

3.创建一个具有参数所指定长整数值的对象

BigDecimal(long)

4.创建一个具有参数所指定以字符串表示的数值的对象

BigDecimal(String)

推荐使用第四种:BigDecimal(String)

 

BigDecimal的常用方法

1.获取值

// 获取值
bigDecimal.byteValue();
bigDecimal.doubleValue();
bigDecimal.longValue();
bigDecimal.intValue();
bigDecimal.shortValue();

2.运算

// 运算
// 每次操作都需要重新赋值才有效果,后面有代码演示
bigDecimal = bigDecimal.add(BigDecimal b); // 加
bigDecimal = bigDecimal.subtract(BigDecimal b); // 减
bigDecimal = bigDecimal.multiply(BigDecimal b); // 乘
bigDecimal = bigDecimal.divide(BigDecimal b); // 除

3.比较大小

// 比较大小
bigDecimal.compareTo(BigDecimal b);

4.设置精度

// 设置精度
bigDecimal = bigDecimal.setScale(int);

5.绝对值

// 绝对值
bigDecimal.abs();

 

BigDecimal的使用示例

1.加减乘除

package com.mikechen.util;

import java.math.BigDecimal;

public class ArithUtil {

    // 除法运算默认精度  
    private static final int DEF_DIV_SCALE = 10;  
  
  
    /** 
     * 精确加法 
     */  
    public static double add(double value1, double value2) {  
        BigDecimal b1 = BigDecimal.valueOf(value1);  
        BigDecimal b2 = BigDecimal.valueOf(value2);  
        return b1.add(b2).doubleValue();  
    }  
  
    /** 
     * 精确减法 
     */  
    public static double sub(double value1, double value2) {  
        BigDecimal b1 = BigDecimal.valueOf(value1);  
        BigDecimal b2 = BigDecimal.valueOf(value2);  
        return b1.subtract(b2).doubleValue();  
    }  
  
    /** 
     * 精确乘法 
     */  
    public static double mul(double value1, double value2) {  
        BigDecimal b1 = BigDecimal.valueOf(value1);  
        BigDecimal b2 = BigDecimal.valueOf(value2);  
        return b1.multiply(b2).doubleValue();  
    }  
  
    /** 
     * 精确除法 使用默认精度 
     */  
    public static double div(double value1, double value2) throws IllegalAccessException {  
        return div(value1, value2, DEF_DIV_SCALE);  
    }  
  
    /** 
     * 精确除法 
     * @param scale 精度 
     */  
    public static double div(double value1, double value2, int scale) throws IllegalAccessException {  
        if(scale < 0) {  
            throw new IllegalAccessException("精确度不能小于0");  
        }  
        BigDecimal b1 = BigDecimal.valueOf(value1);  
        BigDecimal b2 = BigDecimal.valueOf(value2);  
        // return b1.divide(b2, scale).doubleValue();  
        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();  
    }  
 
    
    
    public static void main(String[] args) throws IllegalAccessException {
        double value1=1.2345678912311;
        double value2=9.1234567890123;
        BigDecimal value3=new BigDecimal(Double.toString(value1));
        BigDecimal value4=new BigDecimal(Double.toString(value2));
        System.out.println("精确加法================="+ArithUtil.add(value1, value2));
        System.out.println("精确减法================="+ArithUtil.sub(value1, value2));
        System.out.println("精确乘法================="+ArithUtil.mul(value1, value2));
        System.out.println("精确除法 使用默认精度 ================="+ArithUtil.div(value1, value2));
        System.out.println("精确除法  设置精度================="+ArithUtil.div(value1, value2,20));
    }

2.比较大小

package com.mikechen.util;

import java.math.BigDecimal;

public class ArithUtil {

    // 除法运算默认精度  
    private static final int DEF_DIV_SCALE = 10;  
      
    /** 
     * 比较大小 
     */  
    public static boolean equalTo(BigDecimal b1, BigDecimal b2) {  
        if(b1 == null || b2 == null) {  
            return false;  
        }  
        return 0 == b1.compareTo(b2);  
    }  
    
    
    public static void main(String[] args) throws IllegalAccessException {
        double value1=1.2345678912311;
        double value2=9.1234567890123;
        BigDecimal value3=new BigDecimal(Double.toString(value1));
        BigDecimal value4=new BigDecimal(Double.toString(value2));
        System.out.println("比较大小 ================="+ArithUtil.equalTo(value3, value4));
    }

3.四舍五入

package com.mikechen.util;

import java.math.BigDecimal;

public class ArithUtil {

    // 除法运算默认精度  
    private static final int DEF_DIV_SCALE = 10;  
  
    /** 
     * 四舍五入 
     * @param scale 小数点后保留几位 
     */  
    public static double round(double v, int scale) throws IllegalAccessException {  
        return div(v, 1, scale);  
    }  
      
    
    public static void main(String[] args) throws IllegalAccessException {
        double value1=1.2345678912311;
  
        System.out.println("四舍五入   小数点后保留几位 ================="+ArithUtil.round(value1, 10));
    }

 

BigDecimal的总结

以上我就主要介绍了BigDecimal的构造,以及BigDecimal的常用方法,希望对你掌握BigDecimal有所帮助。

作者简介

陈睿|mikechen,10年+大厂架构经验,BAT资深面试官,就职于阿里巴巴、淘宝、百度等一线互联网大厂。

👇阅读更多mikechen架构文章👇

阿里架构 |双11秒杀 |分布式架构 |负载均衡 |单点登录 |微服务 |云原生 |高并发 |架构师

以上

关注作者「mikechen」公众号,获取更多技术干货!

后台回复架构,即可获取《阿里架构师进阶专题全部合集》,后台回复面试即可获取《史上最全阿里Java面试题总结

评论交流
    说说你的看法