基础篇-BigInteger

先说说基础篇吧。谈起java基础应该是有很多很多的知识点,不是一篇两篇能够说完的。一听到java基础就能想到N多种集合的优缺点、多线程下出现的问题如何解决,java的Atomic原子操作类、jvm结构、jmm模型、jvm调优、各种循环的速度快慢(java基础语法不在复盘范围内)。

今天咱们来聊一个问题,众所周知java接收整数类型是用int和lang,但是int是4字节,long是8字节,都是有范围的,一个字节=8位二进制数,int的4字节最大就是存储的就是32位二进制。最大的数字无非也就是二进制的32个1。转成10进制大概就是42亿多,但是要照顾到正负数和0,所以需要把首位当做符号位,0=正数,1=负数,所以表示数的位数就变为了31位2二进制数,最高2147483647,最低-2147483647,(计算机保存负数是按照反码保存的,在这里不做深究)所以int的整数最大是到21亿多,负数也是-21亿多。long也是同理计算。
因为int是有正负数的所以在二进制的高位第一位是符号位,所以真正代表数字的也就31位,所以最大和最小分别是-21亿多和正21亿多。

现在有这么一个问题,假设你要从一个地方去取一个很长很长的整数(超过了int和long的范围)来本地计算加减法并得到结果,这个时候应该如何处理呢?很多人说用String接收,但是你用String接收下来之后如何计算呢?

通过研究发现java有一个BigInteger类(长浮点数用BigDecimal类)。可以解决这个问题

BigInteger 是java.math包下的类。理论上可以存储无限大的数字,只要你的本地内存吃得消。
接下来咱们讲讲原理:
先一句话概括,BigInteger是通过把整数字符串拆分来存入一个数组内,然后封装了一些运算方法。

使用方法:
通过构造函数来传入整数字符串

	BigInteger bi = new BigInteger("855441231545646434564531454");

读一下加法运算的函数源码:


	public BigInteger add(BigInteger val) {
        if (val.signum == 0)
            return this;
        if (signum == 0)
            return val;
        if (val.signum == signum)
            return new BigInteger(add(mag, val.mag), signum);

        int cmp = compareMagnitude(val);
        if (cmp == 0)
            return ZERO;
        int[] resultMag = (cmp > 0 ? subtract(mag, val.mag)
                           : subtract(val.mag, mag));
        resultMag = trustedStripLeadingZeroInts(resultMag);

        return new BigInteger(resultMag, cmp == signum ? 1 : -1);
    }

这里是源码:
本文贴出的是byte[]为参数的构造函数,也有String的,但是没贴出来可自行查找。

	final int[] mag; // mag就是BigInteger类维护的整数数组

	public BigInteger(byte[] val) {
        if (val.length == 0)
            throw new NumberFormatException("Zero length BigInteger");

        if (val[0] < 0) {
            mag = makePositive(val);
            signum = -1;
        } else {
            mag = stripLeadingZeroBytes(val);
            signum = (mag.length == 0 ? 0 : 1);
        }
        if (mag.length >= MAX_MAG_LENGTH) {
            checkRange();
        }
    }

	private static int[] stripLeadingZeroBytes(byte a[]) {
        int byteLength = a.length;
        int keep;

        // Find first nonzero byte
        for (keep = 0; keep < byteLength && a[keep] == 0; keep++)
            ;

        // Allocate new array and copy relevant part of input array
        int intLength = ((byteLength - keep) + 3) >>> 2;
        int[] result = new int[intLength];
        int b = byteLength - 1;
        for (int i = intLength-1; i >= 0; i--) {
            result[i] = a[b--] & 0xff;
            int bytesRemaining = b - keep + 1;
            int bytesToTransfer = Math.min(3, bytesRemaining);
            for (int j=8; j <= (bytesToTransfer << 3); j += 8)
                result[i] |= ((a[b--] & 0xff) << j);
        }
        return result;
    }

下面提供一些BigInteger封装的一些方法:

add();相加

subtract(); 相减

multiply(); 相乘

divide(); 相除(取整)

remainder(); 取余

pow(); a.pow(b)=a^b

gcd(); 最大公约数

abs(); 绝对值

negate(); 取反数

mod(); a.mod(b)=a%b=a.remainder(b);

max(); min();

punlic int comareTo();

boolean equals(); 是否相等

BigInteger也可以跟基础类型转换,只要基础类型能够放得下:

转换为byte:byteValue()
转换为short:shortValue()
转换为int:intValue()
转换为long:longValue()
转换为float:floatValue()
转换为double:doubleValue()

如果BigInteger的值太大,你非要用int或者long接收的话会报:ArithmeticException异常

以上为 BigInteger 的简介,希望可以在工作和面试中帮到你,有什么不全面或者不对的地方大家多多指出。

猜你喜欢

转载自blog.csdn.net/weixin_42027340/article/details/106640490
今日推荐