java中的BigDecimal使用

文章目录

  • 1、什么是BigDecimal?
  • 2、为什么使用BigDecimal?
  • 3、如何使用BigDecimal?
    • (1)BigDecimal初始化赋值
    • (2)加减乘除运算
    • (3)BigDecimal保留两位小数及舍入模式
    • (4)BigDecimal比较大小
    • (5)BigDecimal其他方法及常量

1、什么是BigDecimal?

BigDecimal属于java.math包,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数。在实际应用中,需要对更大或者更小的数进行运算和处理。

float和double只能用来做科学计算或者是工程计算,在商业计算中(如金融行业)要用java.math.BigDecimal。

BigDecimal所创建的是对象,我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是BigDecimal的对象。构造器是类的特殊方法,专门用来创建对象,特别是带有参数的对象。

2、为什么使用BigDecimal?

我们看如下代码:

public static void main(String[] args) throws Exception {
        System.out.println(0.2 + 0.1);
        System.out.println(0.3 - 0.1);
        System.out.println(0.2 * 0.1);
        System.out.println(0.3 / 0.1);
    }

打印结果:

java中的BigDecimal使用_第1张图片
为何会这样?

原因:不论是float 还是double都是浮点数,而计算机是二进制的,浮点数会失去一定的精确度。

根本原因:十进制值通常没有完全相同的二进制表示形式;十进制数的二进制表示形式可能不精确。只能无限接近于那个值。

但是,在项目中,我们不可能让这种情况出现,特别是金融项目,因为涉及金额的计算都必须十分精确,否则,如果你的微信账户余额显示193.99999999999998,那是一种怎么样的体验?

3、如何使用BigDecimal?

(1)BigDecimal初始化赋值

方法 类型 描述
public BigDecimal(int val) 构造函数 int类型的值生成BigDecimal对象
public BigDecimal(long val) 构造函数 long类型的值生成BigDecimal对象
public BigDecimal(String val) 静态方法 String类型的值转换为BigDecimal类型
public static BigDecimal valueOf(double val) 静态方法 double类型的值转换为BigDecimal类型
public static BigDecimal valueOf(long val) 静态方法 long类型(包含int类型)的值转换为BigDecimal类型

代码示例:

 		BigDecimal b = new BigDecimal("25");
        BigDecimal c = new BigDecimal(12);

        System.out.println(b);
        System.out.println(c);

打印结果:

java中的BigDecimal使用_第2张图片

注意:不建议使用public BigDecimal(double val)方式初始化值

如下代码:

		BigDecimal c = new BigDecimal(12.3);
        System.out.println(c);

打印结果:

java中的BigDecimal使用_第3张图片
如图,也会出现计算的错误。

通常建议优先使用String构造方法。当double必须用作BigDecimal的源时,请使用Double.toString(double)转成String,然后使用String构造方法,或使用BigDecimal的静态方法valueOf:

		BigDecimal b = new BigDecimal("12.3");
        BigDecimal c = BigDecimal.valueOf(7.34325);
        BigDecimal d = new BigDecimal(Double.toString(7.34325));
        System.out.println(b);
        System.out.println(c);
        System.out.println(d);

打印结果:

java中的BigDecimal使用_第4张图片

(2)加减乘除运算

运算法则 对应方法
加法 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) throws Exception {
        System.out.println("计算加法: " + BigDecimal.valueOf(1.9).add(BigDecimal.valueOf(0.2)));
        System.out.println("计算减法: " + BigDecimal.valueOf(1.9).subtract(BigDecimal.valueOf(1.5)));
        System.out.println("计算乘法: " + BigDecimal.valueOf(1.9).multiply(BigDecimal.valueOf(0.2)));
        System.out.println("计算除法: " + BigDecimal.valueOf(1.9).divide(BigDecimal.valueOf(0.2)));
    }

打印结果:

java中的BigDecimal使用_第5张图片
注意点:

  1. BigDecimal的运算结果都是返回了一个新的BigDecimal对象,并不是在原有的对象上进行操作。

代码示例:

public static void main(String[] args)  {
        BigDecimal bigDecimal = new BigDecimal("2");
        System.out.println("bigDecimal计算前的地址是:"+System.identityHashCode(bigDecimal));
        bigDecimal = bigDecimal.add(BigDecimal.valueOf(3));
        System.out.println("bigDecimal计算后的地址是:"+System.identityHashCode(bigDecimal));
    }

打印结果:
java中的BigDecimal使用_第6张图片

  1. 使用divide除法函数除不尽,出现无线循环小数的时候,就需要使用另外精确的小数位数以及舍入模式,不然会出现报错。

代码示例:

public static void main(String[] args)  {
        BigDecimal a = BigDecimal.valueOf(10), b = BigDecimal.valueOf(3);
        System.out.println(a.divide(b));
    }

报错如下:

在这里插入图片描述

解决方法可以采用四舍五入的方式,详情见下文!

(3)BigDecimal保留两位小数及舍入模式

public BigDecimal setScale(int newScale, int roundingMode)

用于格式化小数的方法,第一个值表示保留几位小数,第二个值表示格式化的类型。
8种类型如下:

格式化类型 描述
ROUND_DOWN 舍弃多余位数,如1.55会格式化为1.5,-1.55会格式化为-1.5
ROUND_UP 进位处理,如1.52会格式化为1.6,-1.52会格式化为-1.6
ROUND_HALF_UP 四舍五入,如果舍弃部分>= .5,则进位
ROUND_HALF_DOWN 五舍六入,如果舍弃部分> .5,则进位
ROUND_CEILING 正无穷大方向舍入模式。如果值为正数,则与ROUND_UP模式相同;如果值为负数,则与ROUND_DOWN模式相同
ROUND_FLOOR 负无穷大方向舍入模式。如果值为正数,则与ROUND_DOWN模式相同;如果值为负数,则与ROUND_UP模式相同
ROUND_UNNECESSARY 确认值的小数位数是否与传入第一个参数(保留小数的位数)相等,如果符合则返回值,如果不符抛出异常
ROUND_HALF_EVEN 如果舍弃部门左边的数字为奇数,则与ROUND_HALF_UP模式相同,如果为偶数则与ROUND_HALF_DOWN模式相同

代码示例:

public static void main(String[] args)  {
        BigDecimal a = BigDecimal.valueOf(5.445);
        System.out.println("5.445舍弃多余位数:" + a.setScale(2, BigDecimal.ROUND_DOWN));
        System.out.println("5.445进位处理:" + a.setScale(2, BigDecimal.ROUND_UP));
        System.out.println("5.445四舍五入(舍弃部分>= .5,进位):" + a.setScale(2, BigDecimal.ROUND_HALF_UP));
        System.out.println("5.445四舍五入(舍弃部分未> .5,舍弃):" + a.setScale(2, BigDecimal.ROUND_HALF_DOWN));
        System.out.println("5.446四舍五入(舍弃部分> .5,进位):" + BigDecimal.valueOf(5.446).setScale(2, BigDecimal.ROUND_HALF_DOWN));
    }

打印结果:
java中的BigDecimal使用_第7张图片

(4)BigDecimal比较大小

public int compareTo(BigDecimal val)

BigDecimal类提供的比较值的方法,注意比较的两个值均不能为空。
a.compareTo(b)得到结果 1, 0, -1。

比较结果 描述
1 a 大于b
0 a 等于b
-1 a 小于b

代码示例:

public static void main(String[] args)  {
        BigDecimal a = BigDecimal.valueOf(1);
        BigDecimal b = BigDecimal.valueOf(2);
        BigDecimal c = BigDecimal.valueOf(1);
        BigDecimal d = BigDecimal.ZERO;
        System.out.println("1和2比较结果:" + a.compareTo(b));
        System.out.println("1和1比较结果:" + a.compareTo(c));
        System.out.println("1和0比较判断:" + (a.compareTo(d) > 0) );
    }

打印结果:
java中的BigDecimal使用_第8张图片

注意:实际业务中,不会单纯的比较谁打谁小,而是类似于第三条去判断一个布尔值。

(5)BigDecimal其他方法及常量

代码 类型 描述
BigDecimal.ZERO 常量 初始化一个为0的BigDecimal对象
BigDecimal.ONE 常量 初始化一个为1的BigDecimal对象
BigDecimal.TEN 常量 初始化一个为10的BigDecimal对象
public BigDecimal abs() 方法 求绝对值,不管正数还是负数,都得到正数
public BigDecimal negate() 方法 求相反数,正变负,负变正
public BigDecimal pow(int n) 方法 求乘方,如BigDecimal.valueOf(2).pow(3)的值为8
public BigDecimal max(BigDecimal val) 方法 两值比较,返回最大值
public BigDecimal min(BigDecimal val) 方法 两值比较,返回最小值

你可能感兴趣的:(Java,java基础知识,java,开发语言,算法)