写给自己

Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数。在实际应用中,需要对更大或者更小的数进行运算和处理。float和double只能用来做科学计算或者是工程计算,在商业计算中要用java.math.BigDecimal。BigDecimal所创建的是对象,我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是BigDecimal的对象。构造器是类的特殊方法,专门用来创建对象,特别是带有参数的对象。 ———摘自百度百科
除此之外还有BigInteger位数比integer要长。

创作时间

8XXXX HH:MM:SS

作者

gaox

正文

BigDecimal

正规发音 美 [bɪɡˈdɛsəməl]

构造器

1. 推荐字符串String

  1. public BigDecimal(String val)  将String表示形式转换成BigDecimal

2. 整形变量 int

  1. public BigDecimal(int val)  将int表示形式转换成BigDecimal

3. 不推荐浮点数据 float、double

  1. // 不建议使用
  2. public BigDecimal(double val) double表示形式转换为BigDecimal

4. 不得不使用浮点数据 float、double

  1. // BigDecimal的静态方法valueOf
  2. BigDecimal bDouble1 = BigDecimal.valueOf(2.3);
  3. // 转换成string
  4. BigDecimal bDouble2 = new BigDecimal(Double.toString(2.3));

四则运算 +-x÷bd

  1. BigDecimal b1 = new BigDecimal("56.59");
  2. BigDecimal b2 = new BigDecimal("56.590");
  3. BigDecimal b3 = new BigDecimal("12");
  4. //68.59 加法
  5. System.out.println(b1.add(b3));
  6. //44.59 减法
  7. System.out.println(b1.subtract(b3));
  8. //679.08 乘法
  9. System.out.println(b1.multiply(b3));
  10. //4.72 除法(保留两位小数,向上取余)
  11. System.out.println(b1.divide(b3,2,RoundingMode.HALF_UP));
  12. /* 注意使用divide时不能整除(如2.3/5.9)会这时会报错错:
  13. java.lang.ArithmeticException: Non-terminating decimal expansion;
  14. no exact representable decimal result.
  15. */

除法的解决

divide方法有可以传三个参数

public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)
第一参数表示除数, 第二个参数表示小数点后保留位数,
第三个参数表示舍入模式,只有在作除法运算或四舍五入时才用到舍入模式,有下面这几种

  1. ROUND_CEILING //向正无穷方向舍入
  2. ROUND_DOWN //向零方向舍入
  3. ROUND_FLOOR //向负无穷方向舍入
  4. ROUND_HALF_DOWN //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向下舍入, 例如1.55 保留一位小数结果为1.5
  5. ROUND_HALF_EVEN //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,如果保留位数是奇数,使用ROUND_HALF_UP,如果是偶数,使用ROUND_HALF_DOWN
  6. ROUND_HALF_UP //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向上舍入, 1.55保留一位小数结果为1.6
  7. ROUND_UNNECESSARY //计算结果是精确的,不需要舍入模式
  8. ROUND_UP //向远离0的方向舍入

按照各自的需要,可传入合适的第三个参数。四舍五入采用 ROUND_HALF_UP

需要对BigDecimal进行截断和四舍五入可用setScale方法,例:

  1. public static void main(String[] args)
  2. {
  3. BigDecimal a = new BigDecimal("3.14159");
  4. a = a.setScale(3, RoundingMode.HALF_UP); //保留3位小数,且四舍五入
  5. System.out.println(a);
  6. }
  1. /*
  2. 减乘除其实最终都返回的是一个新的BigDecimal对象,
  3. 因为BigInteger与BigDecimal都是不可变的(immutable)的,在进行每一步运算时,都会产生一个新的对象
  4. */
  1. public static void main(String[] args)
  2. {
  3. BigDecimal a = new BigDecimal("4.5");
  4. BigDecimal b = new BigDecimal("1.5");
  5. a.add(b);
  6. System.out.println(a); //输出4.5. 加减乘除方法会返回一个新的BigDecimal对象,原来的a不变
  7. }

比较运算

1.0 和1.0000 一样么

  1. // 一般的对象用于等于,但是BigDecimal比较特殊,举个例子:
  2. BigDecimal a = BigDecimal.valueOf1.0);
  3. BigDecimal b = BigDecimal.valueOf1.000);
  4. boolean b = a.equals(b);
  5. // b = false ;怎么不相等了呢?因为等于是比较内容,“1.0”和“1.000”当然不一样了

compareTo() 方法

  1. `public int compareTo(BigDecimal val)`<br /> 将此BigDecimal与指定的BigDecimal进行比较。 <br /> 两个BigDecimal对象的价值相等但具有不同的<br /> 比例(如1.01.000)被认为是相等的这种方法。<br /> 该方法优先于<br /> 六个布尔比较运算符(<,==,>,> =,!=,<=)中的每一个的各个方法。<br /> 用于执行这些比较的建议成语是:(x.compareToy)<op> 0),其中<op>是六个比较运算符之一。

-1,0或1,因为BigDecimal数值小于等于或大于val。

  1. //相等
  2. System.out.println("b1 == b2: " + (0 == b1.compareTo(b2)));
  3. //不等于
  4. System.out.println("b1 != b2: " + (0 != b1.compareTo(b2)));
  5. // 大于
  6. System.out.println("b1 > b3: " + (1 == b1.compareTo(b3)));
  7. //小于
  8. System.out.println("b1 < b3: " + (-1 == b1.compareTo(b3)));
  9. //小于等于
  10. System.out.println("b1 <= b2: " + (1 != b1.compareTo(b2)));
  11. //大于等于
  12. System.out.println("b1 >= b3: " + (-1 != b1.compareTo(b3)));
  13. /* 输出结果
  14. b1 == b2: true
  15. b1 != b2: false
  16. b1 > b3: true
  17. b1 < b3: false
  18. b1 <= b2: true
  19. b1 >= b3: true
  20. */
  1. BigDecimal decimal1 = new BigDecimal("1");
  2. BigDecimal decimal1_0 = new BigDecimal("1.0");
  3. BigDecimal decimal0 = new BigDecimal("0");
  4. BigDecimal decimal2 = new BigDecimal("2");
  5. BigDecimal decimal_1_0 = new BigDecimal("-1.0");
  6. System.out.println("1.compareTo(1.0) = "+decimal1.compareTo(decimal1_0));
  7. System.out.println("1.compareTo(0) = "+decimal1.compareTo(decimal0));
  8. System.out.println("1.compareTo(2) = "+decimal1.compareTo(decimal2));
  9. System.out.println("1.compareTo(-1.0) = "+decimal1.compareTo(decimal_1_0));
  10. System.out.println("-1.0.compareTo1.0 = "+decimal_1_0.compareTo(decimal1_0));
  11. /*
  12. 1.compareTo(1.0) = 0
  13. 1.compareTo(0) = 1
  14. 1.compareTo(2) = -1
  15. 1.compareTo(-1.0) = 1
  16. -1.0.compareTo1.0 = -1
  17. */

BigInteger

不可变的任意精度的整数。有时候数据可能超过long型,一旦超过long 型,基本 类型就不能表示了。对于这种超级大数,Java把他变成BigInteger的对象去做。大数的四则运算都是采用方法去完成的。
在java.math包中。

构造器

  1. // 推荐使用string构造
  2. BigInteger b4 = new BigInteger("1");
  3. BigInteger b5 = new BigInteger(String.valueOf(1));

四则运算

参考BigDecimal 四则运算 +-x÷bd

比较

参考BigDecimal 比较运算

结束语

商业计算使用BigDecimal。

尽量使用参数类型为String的构造函数。

BigDecimal都是不可变的(immutable)的,在进行每一步运算时,都会产生一个新的对象,所以在做加减乘除运算时千万要保存操作后的值。

我们往往容易忽略JDK底层的一些实现细节,导致出现错误,需要多加注意。