主要是String转int[]
/** * Translates the String representation of a BigInteger in the * specified radix into a BigInteger. The String representation * consists of an optional minus or plus sign followed by a * sequence of one or more digits in the specified radix. The * character-to-digit mapping is provided by {@code * Character.digit}. The String may not contain any extraneous * characters (whitespace, for example). * * @param val String representation of BigInteger. * @param radix radix to be used in interpreting {@code val}. * @throws NumberFormatException {@code val} is not a valid representation * of a BigInteger in the specified radix, or {@code radix} is * outside the range from {@link Character#MIN_RADIX} to * {@link Character#MAX_RADIX}, inclusive. * @see Character#digit */ public BigInteger(String val, int radix) { int cursor = 0, numDigits; final int len = val.length(); // radix 是否在2-36之间 if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) throw new NumberFormatException("Radix out of range"); if (len == 0) throw new NumberFormatException("Zero length BigInteger"); // Check for at most one leading sign // 检查是否存在多个“+”“-”符号 // 判断正负 int sign = 1; int index1 = val.lastIndexOf('-'); int index2 = val.lastIndexOf('+'); if (index1 >= 0) { if (index1 != 0 || index2 >= 0) { throw new NumberFormatException("Illegal embedded sign character"); } sign = -1; cursor = 1; } else if (index2 >= 0) { if (index2 != 0) { throw new NumberFormatException("Illegal embedded sign character"); } cursor = 1; } if (cursor == len) throw new NumberFormatException("Zero length BigInteger"); // Skip leading zeros and compute number of digits in magnitude // 忽略前置的0 while (cursor < len && Character.digit(val.charAt(cursor), radix) == 0) { cursor++; } // 字符串内全是0的情况,直接返回0值 if (cursor == len) { signum = 0; mag = ZERO.mag; return; } numDigits = len - cursor; signum = sign; // 预分配预期大小的数组。可能太大,但决不可能太小。通常精确。 long numBits = ((numDigits * bitsPerDigit[radix]) >>> 10) + 1; if (numBits + 31 >= (1L << 32)) { reportOverflow(); } int numWords = (int) (numBits + 31) >>> 5; int[] magnitude = new int[numWords]; // Process first (potentially short) digit group // 计算当前进制(radix)中,数组第一位保存的位数 int firstGroupLen = numDigits % digitsPerInt[radix]; if (firstGroupLen == 0) firstGroupLen = digitsPerInt[radix]; String group = val.substring(cursor, cursor += firstGroupLen); magnitude[numWords - 1] = Integer.parseInt(group, radix); // 检查第一个值是否合法 if (magnitude[numWords - 1] < 0) throw new NumberFormatException("Illegal digit"); // 处理剩余的数字 // 获取该进制最大位数 int superRadix = intRadix[radix]; int groupVal = 0; while (cursor < len) { group = val.substring(cursor, cursor += digitsPerInt[radix]); groupVal = Integer.parseInt(group, radix); if (groupVal < 0) throw new NumberFormatException("Illegal digit"); // 向最后一位进行加法操作,再进行一次进位计算 destructiveMulAdd(magnitude, superRadix, groupVal); } // Required for cases where the array was overallocated. // 去掉开头的0 mag = trustedStripLeadingZeroInts(magnitude); if (mag.length >= MAX_MAG_LENGTH) { checkRange(); } } /* * 整数模拟,对应radix(进制)的最大位数和指数方 * intRadix = radix^digitsPerInt[radix] */ private static int digitsPerInt[] = {0, 0, 30, 19, 15, 13, 11, 11, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5}; private static int intRadix[] = {0, 0, 0x40000000, 0x4546b3db, 0x40000000, 0x48c27395, 0x159fd800, 0x75db9c97, 0x40000000, 0x17179149, 0x3b9aca00, 0xcc6db61, 0x19a10000, 0x309f1021, 0x57f6c100, 0xa2f1b6f, 0x10000000, 0x18754571, 0x247dbc80, 0x3547667b, 0x4c4b4000, 0x6b5a6e1d, 0x6c20a40, 0x8d2d931, 0xb640000, 0xe8d4a51, 0x1269ae40, 0x17179149, 0x1cb91000, 0x23744899, 0x2b73a840, 0x34e63b41, 0x40000000, 0x4cfa3cc1, 0x5c13d840, 0x6d91b519, 0x39aa400 }; // Multiply x array times word y in place, and add word z // 计算低位是否需要向高增递交进位 private static void destructiveMulAdd(int[] x, int y, int z) { // Perform the multiplication word by word long ylong = y & LONG_MASK; long zlong = z & LONG_MASK; int len = x.length; long product = 0; long carry = 0; // 计算值后保存int值到数组中,再计算向高位递交的值 for (int i = len-1; i >= 0; i--) { product = ylong * (x[i] & LONG_MASK) + carry; x[i] = (int)product; carry = product >>> 32; } // Perform the addition // 向最后一位进行加法操作,再进行一次进位计算 long sum = (x[len-1] & LONG_MASK) + zlong; x[len-1] = (int)sum; carry = sum >>> 32; for (int i = len-2; i >= 0; i--) { sum = (x[i] & LONG_MASK) + carry; x[i] = (int)sum; carry = sum >>> 32; } } /** * Returns the input array stripped of any leading zero bytes. * Since the source is trusted the copying may be skipped. * 去掉开头的0 */ private static int[] trustedStripLeadingZeroInts(int val[]) { int vlen = val.length; int keep; // Find first nonzero byte for (keep = 0; keep < vlen && val[keep] == 0; keep++) ; return keep == 0 ? val : java.util.Arrays.copyOfRange(val, keep, vlen); }在业务处理中,还遇到过要将char[]转成BigInteger的需求
/* * Constructs a new BigInteger using a char array with radix=10. * Sign is precalculated outside and not allowed in the val. The {@code val} * array is assumed to be unchanged for the duration of the constructor * call. * char[]数组,需要填写正负参数,只能定义10进制内容,还需要确定数组长度 */ BigInteger(char[] val, int sign, int len) { int cursor = 0, numDigits; // Skip leading zeros and compute number of digits in magnitude while (cursor < len && Character.digit(val[cursor], 10) == 0) { cursor++; } if (cursor == len) { signum = 0; mag = ZERO.mag; return; } numDigits = len - cursor; signum = sign; // 预先估计数组大小 int numWords; if (len < 10) { numWords = 1; } else { long numBits = ((numDigits * bitsPerDigit[10]) >>> 10) + 1; if (numBits + 31 >= (1L << 32)) { reportOverflow(); } numWords = (int) (numBits + 31) >>> 5; } int[] magnitude = new int[numWords]; // 处理第一位 int firstGroupLen = numDigits % digitsPerInt[10]; if (firstGroupLen == 0) firstGroupLen = digitsPerInt[10]; magnitude[numWords - 1] = parseInt(val, cursor, cursor += firstGroupLen); // 处理余下的 while (cursor < len) { int groupVal = parseInt(val, cursor, cursor += digitsPerInt[10]); destructiveMulAdd(magnitude, intRadix[10], groupVal); } mag = trustedStripLeadingZeroInts(magnitude); if (mag.length >= MAX_MAG_LENGTH) { checkRange(); } }long转BigInteger也是比较常见的
/** * 将long转成BigInteger,当数值大于int范围时,除以2^32,商为高位,地位直接转int格式 */ private BigInteger(long val) { if (val < 0) { val = -val; signum = -1; } else { signum = 1; } int highWord = (int)(val >>> 32);// 除以2^32,获得进位 if (highWord == 0) { mag = new int[1]; mag[0] = (int)val; } else { mag = new int[2]; mag[0] = highWord; mag[1] = (int)val; } }