[java] API-BigInteger、BigDecimal篇

目录

BigInteger类

常见方法

底层存储方式

BigDecimal类

常见方法

底层存储方式


BigInteger类

平时在存储整数的时候,Java中默认是int类型,int类型有取值范围:-2147483648 ~ 2147483647。如果数字过大,可以使用long类型,但是如果long类型也表示不下怎么办呢?

就需要用到BigInteger,可以理解为:大的整数。理论上最大到42亿的21亿次方

基本上在内存撑爆之前,都无法达到这个上限。

查看API文档,可以看到API文档中关于BigInteger类的定义如下:

BigInteger所在包是在java.math包下,因此在使用的时候就需要进行导包。可以使用BigInteger类进行大整数的计算

常见方法

构造方法

public BigInteger(int num, Random rnd)         
//获取随机大整数,范围:[0 ~ 2的num次方 -1]
public BigInteger(String val)               
//获取指定的大整数
public BigInteger(String val, int radix)    
//获取指定进制的大整数

下面这个不是构造,而是一个静态方法获取BigInteger对象
public static BigInteger valueOf(long val)  
//静态方法获取BigInteger的对象,内部有优化

示例:

    public static void main(String[] args) {
        //对象一旦创建里面的数据不能发生改变

        //1.获取一个随机的大整数
        Random r=new Random();
        BigInteger bd1 = new BigInteger(4,r);//[0 ~ 15]

        //2.获取一个指定的大整数,可以超出long的取值范围
        //细节:字符串中必须是整数,否则会报错
        //BigInteger bd2 = new BigInteger("1.1");//报错
        //BigInteger bd3 = new BigInteger("abc");//报错

        //3.获取指定进制的大整数
        //细节:
        //1.字符串中的数字必须是整数
        //2.字符串中的数字必须要跟进制吻合。
        //比如二进制中,那么只能写0和1,写其他的就报错。
        //BigInteger bd4 = new BigInteger("123", 2);//报错
        //转为十进制
        BigInteger bd4 = new BigInteger("100", 2);
        System.out.println(bd4);//4

        //4.静态方法获取BigInteger的对象,内部有优化
        //细节:
        //1.能表示范围比较小,只能在long的取值范围之内,如果超出long的范围就不行了。
        //2.在内部对常用的数字: -16 ~ 16 进行了优化。
        //  提前把-16~16 先创建好BigInteger的对象,如果多次获取不会重新创建新的。
        BigInteger bd5 = BigInteger.valueOf(16);
        BigInteger bd6 = BigInteger.valueOf(16);
        System.out.println(bd5 == bd6);//true

        BigInteger bd7 = BigInteger.valueOf(17);
        BigInteger bd8 = BigInteger.valueOf(17);
        System.out.println(bd7 == bd8);//false

        //5.对象一旦创建内部的数据不能发生改变
        BigInteger bd9 =BigInteger.valueOf(1);
        BigInteger bd10 =BigInteger.valueOf(2);
        //此时,不会修改参与计算的BigInteger对象中的值
        //而是产生了一个新的BigInteger对象记录
        BigInteger result=bd9.add(bd10);
        System.out.println(result);//3
    }

构造方法小结:

  • 如果BigInteger表示的数字没有超出long的范围,可以用静态方法获取。

  • 如果BigInteger表示的超出long的范围,可以用构造方法获取。

  • 对象一旦创建,BigInteger内部记录的值不能发生改变

  • 只要进行计算都会产生一个新的BigInteger对象

常见成员方法

BigDecimal类中使用最多的还是提供的进行四则运算的方法,如下:

public BigInteger add(BigInteger val)                  
//加法
public BigInteger subtract(BigInteger val)              
//减法
public BigInteger multiply(BigInteger val)              
//乘法
public BigInteger divide(BigInteger val)                
//除法,获取商
public BigInteger[] divideAndRemainder(BigInteger val)   
//除法,获取商和余数
public  boolean equals(Object x)                        
//比较是否相同,已重写,比较变量值
public  BigInteger pow(int exponent)                    
//次幂、次方
public  BigInteger max/min(BigInteger val)              
//返回较大值/较小值
public  int intValue(BigInteger val)                    
//转为int类型整数,超出范围数据有误

代码实现:

    public static void main(String[] args) {
        //1.创建两个BigInteger对象
        BigInteger bd1 = BigInteger.valueOf(10);
        BigInteger bd2 = BigInteger.valueOf(5);

        //2.加法
        BigInteger bd3 = bd1.add(bd2);
        System.out.println(bd3);//15

        //3.除法,获取商和余数
        BigInteger[] arr = bd1.divideAndRemainder(bd2);
        System.out.println(arr[0]);//2 商
        System.out.println(arr[1]);//0 余

        //4.比较是否相同
        boolean result = bd1.equals(bd2);
        System.out.println(result);//false

        //5.次幂
        BigInteger bd4 = bd1.pow(2);
        System.out.println(bd4);//100

        //6.max
        BigInteger bd5 = bd1.max(bd2);//10
        //返回值大的那个对象,不会创建新的对象

        //7.转为int类型整数,超出范围数据有误
        BigInteger bd6 = BigInteger.valueOf(2147483647L);//最大值,不能大于这个数
        int i = bd6.intValue();
        System.out.println(i);


        BigInteger bd6 = BigInteger.valueOf(200);
        double v = bd6.doubleValue();
        System.out.println(v);//200.0
    }

底层存储方式

对于计算机而言,其实是没有数据类型的概念的,都是0101010101,数据类型是编程语言自己规定的,所以在实际存储的时候,先把具体的数字变成二进制的补码,从低位到高位,每32个bit为一组,把每组数据转为十进制,存储在数组中。(了解就行)

数组中最多能存储元素个数:21亿多

数组中每一位能表示的数字:42亿多

理论上,BigInteger能表示的最大数字为:42亿的21亿次方。

但是还没到这个数字,电脑的内存就会撑爆,所以一般认为BigInteger是无限的

存储方式如图所示:

BigDecimal类

看到如下程序:

public class BigDecimalDemo01 {
    public static void main(String[] args) {
        System.out.println(0.09 + 0.01);//0.09999999999999999
    }
}

结果其实是一个丢失精度的结果。为什么会产生精度丢失呢?

在使用float或者double类型的数据在进行数学运算的时候,很有可能会产生精度丢失问题。计算机底层在进行运算的时候,使用的都是二进制数据。当在程序中写了一个十进制数据 ,在进行运算的时候,计算机会将这个十进制数据转换成二进制数据,然后再进行运算,计算完毕以后计算机会把运算的结果再转换成十进制数据用来展示;

如果我们使用的是整数类型的数据进行计算,那么在把十进制数据转换成二进制数据的时候不会存在精度问题;

如果我们的数据是浮点类型的数据,有的时候计算机并不会将这个数据完全转换成一个二进制数据,而是将这个将其转换成一个无限的趋近于这个十进数的二进制数据; 这样使用一个不太准确的数据进行运算的时候, 最终就会造成精度丢失;为了提高精度,Java就提供BigDecimal供我们进行数据运算。

查看API文档,可以看到API文档中关于BigDecimal类的定义如下:

BigDecimal所在包是在java.math包下,因此在使用的时候就需要进行导包。可以使用BigDecimal类进行更加精准的数据计算。

作用

  • 用于小数的精确计算
  • 用来表示很大的小数

常见方法

构造方法

最常用的构造方法:

//1.通过传递double类型的小数来创建对象
//细节:
//这种方式有可能是不精确的,所以不建议使用
//BigDecimal bd1 = new BigDecimal(0.01);
//BigDecimal bd2 = new BigDecimal(0.09);
// system.out.println(bd1);
// system.out.println(bd2);

//2.通过传递字符串表示的小数来创建对象
BigDecimal bd3 = new BigDecimal( val: "0.01");
BigDecimal bd4 = new BigDecimal( val: "0.09");
BigDecimal bd5 = bd3.add(bd4);
System.out.println(bd3);//0.01
System.out.print1n(bd4);//0.09
System.out.println(bd5);//0.10

//3.通过静态方法获取对象
BigDecimal bd6 = BigDecimal.value0f(10);
system.out.print1n(bd6);//10

//细节:
//1.如果要表示的数字不大,没有超出double的取值范围,建议使用静态方法
//2.如果要表示的数字比较大,超出了double的取值范围,建议使用构造方法
//3.如果传递的是0~10之间的整数,包含0,包含10,那么方法会返回已经创建好的对象,不会重新new

常见成员方法

BigDecimal类中使用最多的还是提供的进行四则运算的方法,如下:

public BigDecimal add(BigDecimal value)                // 加法运算
public BigDecimal subtract(BigDecimal value)        // 减法运算
public BigDecimal multiply(BigDecimal value)        // 乘法运算
public BigDecimal divide(BigDecimal value)          // 触发运算

案例1:基本的四则运算

public class BigDecimalDemo01 {
    public static void main(String[] args) {
        // 创建两个BigDecimal对象
        BigDecimal b1 = new BigDecimal("0.3") ;
        BigDecimal b2 = new BigDecimal("4") ;

        // 调用方法进行b1和b2的四则运算,并将其运算结果在控制台进行输出
        System.out.println(b1.add(b2));         //4.3
        System.out.println(b1.subtract(b2));    //-3.7
        System.out.println(b1.multiply(b2));    //1.2
        System.out.println(b1.divide(b2));      //0.075      
    }
}

使用BigDecimal类来完成浮点数的计算不会存在损失精度的问题

案例2:除法的特殊情况

如果使用BigDecimal类型的数据进行除法运算的时候,得到的结果是一个无限循环小数,那么就会报错:ArithmeticException。 如下代码所示:

public class BigDecimalDemo02 {
    public static void main(String[] args) {
        // 创建两个BigDecimal对象
        BigDecimal b1 = new BigDecimal("1") ;
        BigDecimal b2 = new BigDecimal("3") ;

        // 调用方法进行b1和b2的除法运算,并且将计算结果在控制台进行输出
        System.out.println(b1.divide(b2));
    }
}

运行程序进行测试,控制台输出结果如下所示:

Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
    at java.base/java.math.BigDecimal.divide(BigDecimal.java:1716)
    at com.itheima.api.bigdecimal.demo02.BigDecimalDemo02.main(BigDecimalDemo02.java:14)

针对这个问题怎么解决,此时就需要使用到BigDecimal类中另外一个divide方法,如下所示:

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

上述divide方法参数说明:

divisor:           除数对应的BigDecimal对象;
scale:              精确的位数;
roundingMode:       取舍模式;
取舍模式被封装到了RoundingMode这个枚举类中,在这个枚举类中定义了很多种取舍方式。
最常见的取舍方式有如下几个:
UP() , FLOOR(直接删除) , HALF_UP(4舍五入)
可以通过如下格式直接访问这些取舍模式:枚举类名.变量名

如下所示:

public class BigDecimalDemo02 {
    public static void main(String[] args) {
        // 调用方法
        method_03() ;
    }
    // 演示取舍模式HALF_UP
    public static void method_03() {
        // 创建两个BigDecimal对象
        BigDecimal b1 = new BigDecimal("0.3") ;
        BigDecimal b2 = new BigDecimal("4") ;

        // 调用方法进行b1和b2的除法运算,并且将计算结果在控制台进行输出
        System.out.println(b1.divide(b2 , 2 , RoundingMode.HALF_UP));
    }

    // 演示取舍模式FLOOR
    public static void method_02() {
        // 创建两个BigDecimal对象
        BigDecimal b1 = new BigDecimal("1") ;
        BigDecimal b2 = new BigDecimal("3") ;

        // 调用方法进行b1和b2的除法运算,并且将计算结果在控制台进行输出
        System.out.println(b1.divide(b2 , 2 , RoundingMode.FLOOR));
    }

    // 演示取舍模式UP
    public static void method_01() {
        // 创建两个BigDecimal对象
        BigDecimal b1 = new BigDecimal("1") ;
        BigDecimal b2 = new BigDecimal("3") ;

        // 调用方法进行b1和b2的除法运算,并且将计算结果在控制台进行输出
        System.out.println(b1.divide(b2 , 2 , RoundingMode.UP));
    }
}

后期在进行两个数的除法运算的时候,常常使用的是可以设置取舍模式的divide方法

底层存储方式

把数据看成字符串,遍历得到里面的每一个字符,把这些字符在ASCII码表上的值,都存储到数组中。

本文是转载文章,点击查看原文
如有侵权,请联系 lx@jishuguiji.net 删除。