一、是什么

BigInteger是Java中一种特殊的包含类,主要用于处理任意精度的整数。它的数据精度比int(32位-231到231-1)和long(64位-263到263-1)大的多,能够存储和处理超过基本数据类型范围的数字。在数学和计算中,这种类型通常被称为大整数。

1.1. 作用

  • 处理大整数:由于计算机内部使用固定精度的二进制表示法,对于非常大的整数,超过基本数据类型(如int或long)的范围,无法直接存储和计算。这时就需要使用BigInteger这种数据类型;
  • 精确计算:在需要精确计算的场景中,如金融、货币计算、大数分解等,使用BigInteger可以避免由于数据类型精度限制而导致的误差;
  • 加密和安全算法:在加密和安全算法中,BigInteger的高精度运算特性使得它可以用于实现加密和解密算法,以及生成安全的随机数等;
  • 数学和科学计算:在数学和科学计算中,很多公式和算法需要高精度的整数运算,比如高次方程求解、大数分解等,使用BigInteger可以提高计算的精度和可靠性;
  • 灵活的数值范围:igInteger支持任意大小的整数,无论是正数还是负数,因此它可以用于处理非常广泛的数值范围。

注:由于BigInteger使用了大量的内存来存储数字,因此它的性能可能不如基本数据类型。此外,由于BigInteger是静态的,每次使用后必须新建一个实例,不能重复使用已存在的实例。因此,在使用BigInteger时需要权衡精度和性能之间的需求。

二、精度丢失示例代码

2.1. 普通类型计算精度丢失

public class test {
    public static void main(String[] args) {
        // 创建一个非常大的整数,超过了long的最大值
        long largeNum = 9223372036854775807L;
        // 将largeNum乘以一个小数,得到一个小数结果
        double result = (double) largeNum * 10;
        // 输出结果,由于精度限制,结果会有一定的误差
        System.out.println(result);
        // 使用BigInteger来防止精度丢失
        BigInteger bigNum = new BigInteger("9223372036854775807");
        BigInteger resultBig = bigNum.multiply(BigInteger.valueOf((10)));
        // 输出BigInteger的结果,由于BigInteger的高精度运算特性,结果不会有误差
        System.out.println(resultBig);
    }
}

输出结果:
图片.png

2.2. BigInteger计算精度丢失

public class test {
    public static void main(String[] args) {
        // 创建一个非常大的整数,超过了long的最大值
        BigInteger bigNum = new BigInteger("123456789012345678901234567890");
        // 将bigNum乘以一个小数,得到一个小数结果
        BigInteger result = bigNum.multiply(BigInteger.valueOf((long) 0.1));
        // 输出结果,由于精度限制,结果会有一定的误差
        System.out.println(result);
    }
}

输出结果:
图片.png
结论:在含有浮点数的预算中会导致计算结果丢失精度,而不是BigInteger自身丢失精度。

三、构造方法

  • **BigInteger(String val):**将字符串表示形式转化为BigInteger;
  • **BigInteger(byte[] val):**将字节数组表示形式转化为BigInteger;
  • **BigInteger(int signum, byte[] magnitude):**将指定符号和字节数组来构造一个BigInteger;
  • **BigInteger(int numBits, Random rnd)�:**通过指定位数和随机数生成一个BigInteger。

示例代码:

public class test {
    public static void main(String[] args) {
        String numStr = "12345678901234567890";
        BigInteger bigInt = new BigInteger(numStr);
        System.out.println(bigInt);

        byte[] bytes = {1, 2, 3, 4, 5};
        BigInteger bigByte = new BigInteger(bytes);
        System.out.println(bigByte); // 输出

        int sign = -1; // 负数符号
        byte[] magnitude = {1, 2, 3, 4, 5}; // 绝对值的字节数组
        BigInteger bigSign = new BigInteger(sign, magnitude);
        System.out.println(bigSign);

        int numBits = 100; // 指定位数为100位,生成的随机数将在 [0, 2^100) 的范围内(包含0但不包含2^100)
        Random rnd = new Random(); // 创建随机数生成器
        // 使用随机数生成器生成一个具有指定位数的随机数
        BigInteger bigRandom = new BigInteger(numBits, rnd);
        System.out.println(bigRandom);
    }
}

输出结果:
图片.png

四、运算

4.1. 加减乘除

示例代码:

public class test {
    public static void main(String[] args) {
        //创建两个BigInteger对象
        BigInteger bi1 = BigInteger.valueOf(100);
        BigInteger bi2 = BigInteger.valueOf(20);

        //加法
        BigInteger bi3 = bi1.add(bi2);
        System.out.println(bi3);

        //减法
        BigInteger bi4 = bi1.subtract(bi2);
        System.out.println(bi4);

        //乘法
        BigInteger bi5 = bi1.multiply(bi2);
        System.out.println(bi3);

        //除法 获取商和余数
        BigInteger[] arr = bi1.divideAndRemainder(bi2);
        System.out.println(arr.length);
        System.out.println(arr[0]); //商
        System.out.println(arr[1]); //余数
    }
}

输出结果:
图片.png

五、比较大小

5.1. compareTo

public class test {
    public static void main(String[] args) {
        BigInteger b1 = new BigInteger("123");
        BigInteger b2 = new BigInteger("1223");
        int result = b1.compareTo(b2);
        System.out.println(result);
    }
}

输出结果:
图片.png

5.2. equals

public class test {
    public static void main(String[] args) {
        BigInteger b1 = new BigInteger("123");
        BigInteger b2 = new BigInteger("1223");
        boolean result = b1.equals(b2);
        System.out.println(result);
    }
}

输出结果:
图片.png

5.3. compareTo和equels区别

compareTo方法比较的是数值大小,不考虑符号。如果当前对象小于参数对象,返回 -1;如果等于,返回 0;如果大于,返回 1。
equles方法则同时考虑数值和符号。只有当两个BigInteger对象的值和符号都相同时,才会返回 true。

六、位运算

6.1. 位运算

public class test {
    public static void main(String[] args) {
        BigInteger b1 = new BigInteger("1010", 2);
        BigInteger b2 = new BigInteger("1100", 2);
        BigInteger and = b1.and(b2); //按位与,纵向对比,两位全为1,该位才为1  1000
        BigInteger or = b1.or(b2); //按位或,纵向对比,只要有1,该位就为1  1110
        BigInteger xor = b1.xor(b2); //按位异或,纵向对比,相同为0,不同为1  0110
        //按位取反,逐位取反, 0101,按位取反操作在Java中会根据二进制补码的形式来计算负数(1011)。
        // 因此,对于正数,按位取反操作会得到一个负数;对于负数,按位取反操作会得到一个正数
        BigInteger not = b1.not();

        System.out.println(and);
        System.out.println(or);
        System.out.println(xor);
        System.out.println(not);
    }
}

输出结果:
图片.png

6.2. 位移动

public class test {
    public static void main(String[] args) {
        BigInteger b1 = new BigInteger("1010", 2);
        BigInteger left = b1.shiftLeft(2); //向左移动两个二进制位 101000
        BigInteger right = b1.shiftRight(2); //向右移动一个二进制位 0010

        System.out.println(left);
        System.out.println(right);
    }
}

输出结果:
图片.png

七、注意事项

BigInteger是Java中用于表示任意精度的整数的类。它提供了许多用于操作大整数的静态方法,如加法、减法、乘法、除法、模运算等。它可以用于大数计算、密码学、科学计算和金融领域等场景。
在使用BigInteger时,需要注意以下事项:

  • 精度问题:由于BigInteger采用高精度的算法,因此在处理大整数时可能会占用大量内存和计算资源。需要合理控制整数的范围和精度,避免造成不必要的性能损耗。
  • 溢出问题:当进行大整数运算时,可能会出现溢出的情况,导致结果不正确。需要合理设计算法和数据结构,避免溢出问题的发生。
  • 空指针异常:在使用BigInteger的某些方法时,如toBigInteger()方法,可能会抛出NullPointerException异常。需要在使用这些方法前确保BigInteger对象不为空。
  • 精度损失:在进行浮点数和整数的混合运算时,可能会出现精度损失的情况。需要合理选择运算顺序和数据类型,避免精度损失的发生。
  • 符号处理:在处理负数时,需要注意符号的处理方式。BigInteger采用二进制补码表示法,符号位在最高位(最左边的一位),其余位表示数值。对于负数,符号位为1,其余位为该数的二进制补码表示。
Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐