BigDemical

BigDecimal类:不可变的、任意精度的有符号十进制数,可以解决数据丢失问题。

  1. public static void main(String[] args) {
  2. System.out.println(0.09 + 0.01); // 0.09999999999999999
  3. System.out.println(1.0 - 0.32); // 0.6799999999999999
  4. System.out.println(1.015 * 100); // 101.49999999999999
  5. System.out.println(1.301 / 100); // 0.013009999999999999
  6. System.out.println(1.0 - 0.12); // 0.88
  7. System.out.println(new BigDecimal(12.45));// 12.44999999999999928945726423989981412
  8. // 上面这个12.45,其实是double类型的,容易丢失精度
  9. System.out.println(new BigDecimal("12.45"));// 12.45
  10. }

结果和我们想的有一点点不一样,这是因为浮点数类型的数据存储和整数不一样导致的。 它们大部分的时候,都是带有有效数字位。由于在运算的时候,float类型和double很容易丢失精度, 所以,为了能精确的表示、计算浮点数,Java提供了BigDecimal。

BigDecimal的常用成员方法:

  1. public BigDecimal(String val) //构造方法
  2. public BigDecimal add(BigDecimal augend) //加
  3. public BigDecimal subtract(BigDecimal subtrahend)//减
  4. public BigDecimal multiply(BigDecimal multiplicand) //乘
  5. public BigDecimal divide(BigDecimal divisor) //除
  6. public BigDecimal divide(BigDecimal divisor,int scale,int roundingMode)//除法,scale:几位小数,roundingMode:如何舍取

使用BigDecimal改进

  1. public static void main(String[] args) {
  2. /*System.out.println(0.09 + 0.01);
  3. System.out.println(1.0 - 0.32);
  4. System.out.println(1.015 * 100);
  5. System.out.println(1.301 / 100);
  6. System.out.println(1.0 - 0.12);*/
  7. BigDecimal bd1 = new BigDecimal("0.09");
  8. BigDecimal bd2 = new BigDecimal("0.01");
  9. System.out.println("add:" + bd1.add(bd2));//add:0.10
  10. BigDecimal bd3 = new BigDecimal("1.0");
  11. BigDecimal bd4 = new BigDecimal("0.32");
  12. System.out.println("subtract:" + bd3.subtract(bd4));//subtract:0.68
  13. BigDecimal bd5 = new BigDecimal("1.015");
  14. BigDecimal bd6 = new BigDecimal("100");
  15. System.out.println("multiply:" + bd5.multiply(bd6));//multiply:101.500
  16. BigDecimal bd7 = new BigDecimal("1.301");
  17. BigDecimal bd8 = new BigDecimal("100");
  18. System.out.println("divide:" + bd7.divide(bd8));//divide:0.01301
  19. //四舍五入
  20. System.out.println("divide:"
  21. + bd7.divide(bd8, 3, BigDecimal.ROUND_HALF_UP));//保留三位有效数字
  22. //divide:0.013
  23. System.out.println("divide:"
  24. + bd7.divide(bd8, 8, BigDecimal.ROUND_HALF_UP));//保留八位有效数字
  25. //divide:0.01301000
  26. }

舍入模式

  • ROUND_UP

    • 定义:远离零方向舍入。
    • 解释:始终对非零舍弃部分前面的数字加 1。注意,此舍入模式始终不会减少计算值的绝对值。
    • 图示:image.png
    • 非0时,舍弃小数后(整数部分)加1,比如12.49结果为13,-12.49结果为 -13
  • ROUND_CEILING

    • 定义:向正无限大方向舍入。
    • 解释:正数,则做 ROUND_UP 操作;负数,则做 ROUND_DOWN 操作 。注意,此舍入模式始终不会减少计算值。
    • 图示:image.png
  • ROUND_DOWN:直接舍弃小数

    • 定义:向零方向舍入。
    • 解释:从不对舍弃部分前面的数字加 1(即截尾)。注意,此舍入模式始终不会增加计算值的绝对值。
    • 图示:image.png
  • ROUND_FLOOR:

    • 定义:向负无限大方向舍入。
    • 解释:正数,则做 ROUND_DOWN 操作;负数,则做 ROUND_UP 操作。 注意,此舍入模式始终不会增加计算值。
    • 图示:image.png
  • ROUND_HALF_UP:四舍五入(取更近的整数)

    • 定义:向最接近的数字方向舍入,如果与两个相邻数字的距离相等,则向上舍入。
    • 解释:如果被舍弃部分 >= 0.5,则舍入行为同 RoundingMode.UP;否则舍入行为同RoundingMode.DOWN。注意,此舍入模式就是四舍五入。
    • 图示:image.png
  • ROUND_HALF_DOWN:跟ROUND_HALF_UP 差别仅在于0.5时会向下取整

    • 定义:向最接近的数字方向舍入,如果与两个相邻数字的距离相等,则向下舍入。
    • 解释:如果被舍弃部分 > 0.5,则舍入行为同 RoundingMode.UP;否则舍入行为同RoundingMode.DOWN。注意,此舍入模式就是通常讲的五舍六入。
    • 图示:image.png
  • ROUND_HALF_EVEN:取最近的偶数

    • 定义:向最接近数字方向舍入,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。
    • 解释:如果舍弃部分左边的数字为奇数,则舍入行为同 RoundingMode.HALF_UP;如果为偶数,则舍入行为同RoundingMode.HALF_DOWN。
    • 注意,在重复进行一系列计算时,根据统计学,此舍入模式可以在统计上将累加错误减到最小。此舍入模式也称为“银行家舍入法”,主要在美国使用。此舍入模式类似于 Java 中对float 和double 算法使用的舍入策略。
    • 图示:image.png
  • ROUND_UNNECESSARY:不需要取整,如果存在小数位,就抛ArithmeticException 异常

    • 定义:用于断言请求的操作具有精确结果,因此不发生舍入。
    • 解释:计算结果是精确的,不需要舍入,若结果的小数位数>要求保留的位数,抛出 ArithmeticException。

BigInteger

BigInteger:可以让超过Integer范围内的数据进行运算

  1. public static void main(String[] args) {
  2. Integer num = new Integer("2147483647");
  3. System.out.println(num);
  4. //Integer num2 = new Integer("2147483648");
  5. // Exception in thread "main" java.lang.NumberFormatException: For input string: "2147483648"
  6. //System.out.println(num2);
  7. // 通过 BigIntege来创建对象
  8. BigInteger num2 = new BigInteger("2147483648");
  9. System.out.println(num2);
  10. }
  • BigInteger的常用成员方法:
  1. public BigInteger add(BigInteger val) //加
  2. public BigInteger subtract(BigInteger val) //减
  3. public BigInteger multiply(BigInteger val) //乘
  4. public BigInteger divide(BigInteger val) //除
  5. public BigInteger[] divideAndRemainder(BigInteger val)//返回商和余数的数组
  • 使用实例:
  1. public class BigIntegerDemo {
  2. public static void main(String[] args) {
  3. Integer num = new Integer("2147483647");
  4. System.out.println(num);
  5. //Integer num2 = new Integer("2147483648");
  6. // Exception in thread "main" java.lang.NumberFormatException: For input string: "2147483648"
  7. //System.out.println(num2);
  8. // 通过 BigIntege来创建对象
  9. BigInteger num2 = new BigInteger("2147483648");
  10. System.out.println(num2);
  11. }
  12. }
  13. public class BigIntegerDemo2 {
  14. public static void main(String[] args) {
  15. BigInteger bi1 = new BigInteger("100");
  16. BigInteger bi2 = new BigInteger("50");
  17. // public BigInteger add(BigInteger val):加
  18. System.out.println("add:" + bi1.add(bi2)); //add:150
  19. // public BigInteger subtract(BigInteger Val):减
  20. System.out.println("subtract:" + bi1.subtract(bi2));//subtract:50
  21. // public BigInteger multiply(BigInteger val):乘
  22. System.out.println("multiply:" + bi1.multiply(bi2));//multiply:5000
  23. // public BigInteger divide(BigInteger val):除
  24. System.out.println("divide:" + bi1.divide(bi2));//divide:2
  25. // public BigInteger[] divideAndRemainder(BigInteger val):返回商和余数的数组
  26. BigInteger[] bis = bi1.divideAndRemainder(bi2);
  27. System.out.println("divide:" + bis[0]);//divide:2
  28. System.out.println("remainder:" + bis[1]);//remainder:0
  29. }
  30. }