Java BigInteger add方法
写了个菲波那切数列的递归,刚开始使用int来返回结果,随便输入个n(得到斐波那契第n个数),结果发现数据变成负数了,明显是溢出了。
int数据类型有四个字节,最大可以实现的数是2的31次方-1。
然后打算使用long类型,结果当我输入n=666时,还是溢出了。long(8字节)类型数据的最大值是2的63次方-1。
具体类型的最大最小值可看下方:
所以现在问题就来了,如果想实现一个超大数的整数,应该使用什么呢?
对了,就是 BigInteger。
众所周知,斐波那契数列是前两个数值加起来,所以我就来看了下Biginteger是如何实现add的。
代码如下:
/** * Returns a BigInteger whose value is {@code (this + val)}. * * @param val value to be added to this BigInteger. * @return {@code this + val} */ 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); }
/**
* Adds the contents of the int arrays x and y. This method allocates
* a new int array to hold the answer and returns a reference to that
* array.
*/
private static int[] add(int[] x, int[] y) {
// If x is shorter, swap the two arrays
if (x.length < y.length) {
int[] tmp = x;
x = y;
y = tmp;
}
int xIndex = x.length;
int yIndex = y.length;
int result[] = new int[xIndex];
long sum = 0;
if (yIndex == 1) {
sum = (x[--xIndex] & LONG_MASK) + (y[0] & LONG_MASK) ;
result[xIndex] = (int)sum;
} else {
// Add common parts of both numbers
while (yIndex > 0) {
sum = (x[--xIndex] & LONG_MASK) +
(y[--yIndex] & LONG_MASK) + (sum >>> 32);
result[xIndex] = (int)sum;
}
}
// Copy remainder of longer number while carry propagation is required
boolean carry = (sum >>> 32 != 0);
while (xIndex > 0 && carry)
carry = ((result[--xIndex] = x[xIndex] + 1) == 0);
// Copy remainder of longer number
while (xIndex > 0)
result[--xIndex] = x[xIndex];
// Grow result if necessary
if (carry) {
int bigger[] = new int[result.length + 1];
System.arraycopy(result, 0, bigger, 1, result.length);
bigger[0] = 0x01;
return bigger;
}
return result;
}
最终结果
最后贴上斐波那契数列递归实现方法:
private static BigInteger getFibonacciN(int n) { if(n == 1 || n == 2) { return BigInteger.ONE; } return cycle(BigInteger.ONE, BigInteger.ONE, n -3); } private static BigInteger cycle(BigInteger s, BigInteger e, int n) { if(n == 0) { return s.add(e); } return cycle(e, s.add(e), --n); }
如上。
一点浩然气,千里快哉风!