如今什么事都动不动大数据了。连个int也level up成了BigInteger。在一些场景彷佛还不得不使用它。java
因而有人贱贱地问:“这个天到底有多大呢?”数组
不,应该是“这个BigInteger到底有多大呢?”大数据
让咱们来看看BigInteger的内部结构吧。this
在BigInteger中,一个大int实际上是由一个int数组实现的,即mag。还有一个int数值signum,用来做为正负标记。spa
public class BigInteger extends Number implements Comparable<BigInteger> { /** * The signum of this BigInteger: -1 for negative, 0 for zero, or * 1 for positive. Note that the BigInteger zero <i>must</i> have * a signum of 0. This is necessary to ensures that there is exactly one * representation for each BigInteger value. * * @serial */ final int signum; /** * The magnitude of this BigInteger, in <i>big-endian</i> order: the * zeroth element of this array is the most-significant int of the * magnitude. The magnitude must be "minimal" in that the most-significant * int ({@code mag[0]}) must be non-zero. This is necessary to * ensure that there is exactly one representation for each BigInteger * value. Note that this implies that the BigInteger zero has a * zero-length mag array. */ final int[] mag;
那么,如何将一个范围大于int范围的数存在BigInteger的mag数组中呢?code
BigInteger有不少重载的构造器,咱们挑选其中一个来讲明就明白了:ci
/** * Constructs a BigInteger with the specified value, which may not be zero. */ private BigInteger(long val) { if (val < 0) { val = -val; signum = -1; } else { signum = 1; } int highWord = (int)(val >>> 32); if (highWord==0) { mag = new int[1]; mag[0] = (int)val; } else { mag = new int[2]; mag[0] = highWord; mag[1] = (int)val; } }
咱们能够看到,对于long长度为8字节,正好是两个int的大小。在上面的构造器中,先经过向右移位32位,取得long的高32位的数,若是为0,则表示long的实际值并无超过int的范围,因而mag数组只申请一个int的大小,保存long的低32位便可;若是不为0,则说明long的实际值已经超出int的范围,这时候,mag申请两个int大小,将高位32位存在mag[0],低位32位存在mag[1]。
element
也就是位数高的存在前面,位数低的存在后面。it
好吧,回到原先的问题,BigInteger有多大?io
mag既然是数组,那么它的长度收到下标范围的影响,即mag的个数不会超过int的最大值,即2的31次方-1,即2147483647。那么每一个int是32位。那么mag所可以大表的位数是2147483647*32。
因此,BigInteger的范围应该是[-22147483647*32-1 ,22147483647*32-1 -1]