先说说基础篇吧。谈起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 的简介,希望可以在工作和面试中帮到你,有什么不全面或者不对的地方大家多多指出。