LargeInteger

 
  1. import java.math.BigInteger;
  2. /**  
  3.  * 超大整数加减乘除:  
  4.  * 题目要求:如果系统要使用超大整数(超过long的范围),请你设计一个数据结构来存储这种超大型数字以及设计一种算法来实现超大整数的加法运算  
  5.  * @author Jason Huang  
  6.  *  
  7.  */ 
  8. public class LargeInteger {
  9.     // 第一位存储符号,第二位开始,从低位到高位存储数据,每个byte存储十进制数字两位,即该存储结构为100进制
  10.     private byte[] data = null;
  11.     private LargeInteger(byte[] data) {
  12.         if (data == null) {
  13.             throw new NumberFormatException();
  14.         }
  15.         this.data = copy(data, -1);
  16.     }
  17.     public LargeInteger(LargeInteger num) {
  18.         this(num.data);
  19.     }
  20.     public LargeInteger(String exp) {
  21.         // 转换成char array
  22.         char[] chars = exp.toCharArray();
  23.         // 获取第一个字母
  24.         char chr = chars[0];
  25.         // 获取左边第一个有效数字的位置
  26.         int left = (chr == '-' || chr == '+') ? 1 : 0;
  27.         // 获取byte array的长度
  28.         int length = (chars.length - left + 3) / 2;
  29.         // 建立byte array
  30.         data = new byte[length];
  31.         // 存储正负符号
  32.         data[0] = (byte) (chr == '-' ? 0x1 : 0x0);
  33.         int index = 1;
  34.         // 从低位到高位处理数字
  35.         for (int i = chars.length - 1; i >= left;) {
  36.             // 个位数
  37.             int num1 = chars[i--] - '0';
  38.             // 十位数
  39.             int num10 = i >= left ? chars[i--] - '0' : 0;
  40.             // 含有非法字符时抛出错误
  41.             if (num1 < 0 || num1 > 9 || num10 < 0 || num10 > 9) {
  42.                 throw new NumberFormatException();
  43.             }
  44.             data[index++] = (byte) (num10 * 10 + num1);
  45.         }
  46.     }
  47.     private static byte[] copy(byte[] bytes, int append) {
  48.         if (bytes == null) {
  49.             throw new NumberFormatException();
  50.         }
  51.         if (bytes.length <= 1) {
  52.             return new byte[2];
  53.         }
  54.         //System.out.println("copy1: " + toString(bytes));
  55.         int length = bytes.length;
  56.         int right = length - 1;
  57.         if (append >= 0) {
  58.             length += append;
  59.         } else {
  60.             for (; right >= 2; right--) {
  61.                 if (bytes[right] > 0x0) {
  62.                     break;
  63.                 }
  64.             }
  65.             length = right + 1;
  66.         }
  67.         byte[] other = new byte[length];
  68.         for (int i = 0; i <= right; i++) {
  69.             other[i] = bytes[i];
  70.         }
  71.         if (isZero(other)) {
  72.             other[0] = 0x0;
  73.         }
  74.         //System.out.println("copy2: " + toString(other));
  75.         return other;
  76.     }
  77.     private static byte[] subarray(byte[] bytes, int beginIndex, int length) {
  78.         if (bytes == null || bytes.length <= 1) {
  79.             throw new NumberFormatException();
  80.         }
  81.         //System.out.println("subarray: " + toString(bytes));
  82.         //System.out.println("beginIndex: " + beginIndex);
  83.         //System.out.println("length: " + length);
  84.         if (beginIndex < 0 || length < 1) {
  85.             //System.out.println("beginIndex: " + beginIndex);
  86.             //System.out.println("length: " + length);
  87.             //System.out.println("bytes.length: " + bytes.length);
  88.             throw new IndexOutOfBoundsException();
  89.         }
  90.         byte[] other = new byte[length];
  91.         other[0] = bytes[0];
  92.         for (int i = 1; i < length && i + beginIndex < bytes.length; i++) {
  93.             //System.out.println("i: " + i);
  94.             //System.out.println("beginIndex: " + beginIndex);
  95.             //System.out.println("length: " + length);
  96.             //System.out.println("bytes.length: " + bytes.length);
  97.             other[i] = bytes[i + beginIndex];
  98.         }
  99.         //System.out.println("other: " + toString(other));
  100.         return other;
  101.     }
  102.     private static byte[] shift(byte[] bytes, int n) {
  103.         if (bytes == null || bytes.length <= 1) {
  104.             throw new NumberFormatException();
  105.         }
  106.         byte[] other = new byte[bytes.length + n];
  107.         other[0] = bytes[0];
  108.         for (int i = 1; i < bytes.length; i++) {
  109.             other[i + n] = bytes[i];
  110.         }
  111.         return other;
  112.     }
  113.     private static byte[] copy(int[] nums) {
  114.         if (nums == null) {
  115.             throw new NumberFormatException();
  116.         }
  117.         if (nums.length <= 1) {
  118.             return new byte[2];
  119.         }
  120.         //System.out.println("copy1: " + toString(nums));
  121.         byte[] other = new byte[nums.length];
  122.         other[0] = (byte) nums[0];
  123.         int over = 0;
  124.         int num = 0;
  125.         for (int i = 1; i < nums.length; i++) {
  126.             over += nums[i];
  127.             other[i] = (byte) (over % 100);
  128.             over /= 100;
  129.         }
  130.         return copy(other, -1);
  131.     }
  132.     public int signum() {
  133.         return compareTo(this.data, new byte[2]);
  134.     }
  135.     private static byte[] abs(byte[] bytes) {
  136.         byte[] other = copy(bytes, -1);
  137.         other[0] = 0x0;
  138.         return other;
  139.     }
  140.     public static LargeInteger abs(LargeInteger num) {
  141.         return new LargeInteger(abs(num.data));
  142.     }
  143.     public LargeInteger abs() {
  144.         return new LargeInteger(abs(this.data));
  145.     }
  146.     private static byte[] negate(byte[] bytes) {
  147.         byte[] other = copy(bytes, -1);
  148.         other[0] ^= 0x1;
  149.         return other;
  150.     }
  151.     public static LargeInteger negate(LargeInteger num) {
  152.         return new LargeInteger(negate(num.data));
  153.     }
  154.     public LargeInteger negate() {
  155.         return new LargeInteger(negate(this.data));
  156.     }
  157.     private static boolean isZero(byte[] bytes) {
  158.         if (bytes == null) {
  159.             throw new NumberFormatException();
  160.         }
  161.         for (int i = 1; i < bytes.length; i++) {
  162.             if (bytes[i] != 0x0) {
  163.                 return false;
  164.             }
  165.         }
  166.         return true;
  167.     }
  168.     private static int compareTo(byte[] bytes1, byte[] bytes2) {
  169.         if (bytes1 == null || bytes2 == null) {
  170.             throw new NumberFormatException();
  171.         }
  172.         if (isZero(bytes1) && isZero(bytes2)) {
  173.             return 0;
  174.         } else if (isZero(bytes1)) {
  175.             return bytes2[0] == 0x1 ? 1 : -1;
  176.         } else if (isZero(bytes2)) {
  177.             return bytes1[0] == 0x1 ? -1 : 1;
  178.         } else if (bytes1[0] > bytes2[0]) {
  179.             return -1;
  180.         } else if (bytes1[0] < bytes2[0]) {
  181.             return 1;
  182.         } else if (bytes1[0] == 0x1) {
  183.             return compareTo(abs(bytes2), abs(bytes1));
  184.         }
  185.         byte[] other1 = copy(bytes1, -1);
  186.         byte[] other2 = copy(bytes2, -1);
  187.         if (other1.length < other2.length) {
  188.             return -1;
  189.         } else if (other1.length > other2.length) {
  190.             return 1;
  191.         } else {
  192.             for (int i = other1.length - 1; i >= 1; i--) {
  193.                 if (other1[i] < other2[i]) {
  194.                     return -1;
  195.                 } else if (other1[i] > other2[i]) {
  196.                     return 1;
  197.                 }
  198.             }
  199.             return 0;
  200.         }
  201.     }
  202.     public static int compareTo(LargeInteger num1, LargeInteger num2) {
  203.         return compareTo(num1.data, num2.data);
  204.     }
  205.     public int compareTo(LargeInteger num) {
  206.         return compareTo(this.data, num.data);
  207.     }
  208.     private static byte[] add(byte[] data1, byte[] data2) {
  209.         if (data1 == null || data2 == null) {
  210.             throw new NumberFormatException();
  211.         }
  212.         if (data1[0] != data2[0]) {
  213.             // 如果正负号相异,则A+B = A-(-B)
  214.             return subtract(data1, negate(data2));
  215.         }
  216.         //System.out.println("data1: " + toString(data1));
  217.         //System.out.println("data2: " + toString(data2));
  218.         // 复制A,B,并加长一位,以保证进位
  219.         int length = data1.length > data2.length ? data1.length + 1 : data2.length + 1;
  220.         // byte1复制A,被加数,并作为结果
  221.         byte[] byte1 = copy(data1, length - data1.length);
  222.         // byte2复制B,加数
  223.         byte[] byte2 = copy(data2, length - data2.length);
  224.         // 因为AB同正负号,所以符号不变
  225.         byte1[0] = data1[0];
  226.         // 进位
  227.         int over = 0;
  228.         // 运算位
  229.         int num = 0;
  230.         // 从低位到高位相加计算
  231.         for (int i = 1; i < byte1.length; i++) {
  232.             // 相应位再加进位,相加
  233.             num = byte1[i] + byte2[i] + over;
  234.             //System.out.println("num: " + num);
  235.             if (num >= 100) {
  236.                 // 有进位
  237.                 over = 1;
  238.                 num -= 100;
  239.             } else {
  240.                 // 无进位
  241.                 over = 0;
  242.             }
  243.             byte1[i] = (byte) num;
  244.         }
  245.         return byte1;
  246.     }
  247.     public LargeInteger add(LargeInteger... nums) {
  248.         byte[] augend = this.data;
  249.         for (LargeInteger num : nums) {
  250.             augend = add(augend, num.data);
  251.         }
  252.         return new LargeInteger(augend);
  253.     }
  254.     private static byte[] subtract(byte[] data1, byte[] data2) {
  255.         if (data1 == null || data2 == null) {
  256.             throw new NumberFormatException();
  257.         }
  258.         //System.out.println("data1: " + toString(data1));
  259.         //System.out.println("data2: " + toString(data2));
  260.         if (data1[0] != data2[0]) {
  261.             // 如果正负号相异,则A-B = A+(-B)
  262.             return add(data1, negate(data2));
  263.         } else if (compareTo(abs(data1), abs(data2)) < 0) {
  264.             // 如果A的绝对值>B的绝对值,则A-B = -(B-A),以保证结果与被减数同符号
  265.             return negate(subtract(data2, data1));
  266.         }
  267.         // data复制A,被减数,并作为结果
  268.         byte[] data = copy(data1, 0);
  269.         // 结果与被减数同符号
  270.         data[0] = data1[0];
  271.         // 退位
  272.         int over = 0;
  273.         // 运算位
  274.         int num = 0;
  275.         for (int i = 1; i < data.length; i++) {
  276.             // 相应位相减,再减退位
  277.             num = data[i] - (i >= data2.length ? 0 : data2[i]) - over;
  278.             //System.out.println("num: " + num);
  279.             if (num < 0) {
  280.                 // 有退位
  281.                 over = 1;
  282.                 num += 100;
  283.             } else {
  284.                 // 无退位
  285.                 over = 0;
  286.             }
  287.             data[i] = (byte) num;
  288.         }
  289.         return data;
  290.     }
  291.     public LargeInteger subtract(LargeInteger... nums) {
  292.         byte[] minuend = this.data;
  293.         for (LargeInteger num : nums) {
  294.             minuend = subtract(minuend, num.data);
  295.         }
  296.         return new LargeInteger(minuend);
  297.     }
  298.     private static byte[] multiply(byte[] data1, byte[] data2) {
  299.         if (data1 == null || data2 == null) {
  300.             throw new NumberFormatException();
  301.         }
  302.         //System.out.println("data1: " + toString(data1));
  303.         //System.out.println("data2: " + toString(data2));
  304.         int[] data = new int[data1.length + data2.length];
  305.         data[0] = data1[0] ^ data2[0];
  306.         int num = 0;
  307.         for (int i = 1; i < data1.length; i++) {
  308.             for (int j = 1; j < data2.length; j++) {
  309.                 num = data1[i] * data2[j];
  310.                 data[i + j - 1] += num;
  311.             }
  312.         }
  313.         return copy(data);
  314.     }
  315.     public LargeInteger multiply(LargeInteger... nums) {
  316.         byte[] multiplicand = this.data;
  317.         for (LargeInteger num : nums) {
  318.             multiplicand = multiply(multiplicand, num.data);
  319.         }
  320.         return new LargeInteger(multiplicand);
  321.     }
  322.     private static byte[][] divide(byte[] data1, byte[] data2) {
  323.         if (data1 == null || data2 == null) {
  324.             throw new NumberFormatException();
  325.         } else if (compareTo(data2, new byte[2]) == 0) {
  326.             //System.out.println("data2: " + toString(data2));
  327.             throw new ArithmeticException();
  328.         }
  329.         //System.out.println("data1: " + toString(data1));
  330.         //System.out.println("data2: " + toString(data2));
  331.         byte[] bytes1 = abs(copy(data1, -1));
  332.         byte[] bytes2 = abs(copy(data2, -1));
  333.         byte[][] result = new byte[bytes1.length - bytes2.length + 2][2];
  334.         if (bytes1.length < bytes2.length) {
  335.             result[0] = new byte[2];
  336.             result[1] = bytes1;
  337.             return result;
  338.         }
  339.         byte[] result1 = new byte[bytes1.length - bytes2.length + 2];
  340.         result1[0] = (byte) (data1[0] ^ data2[0]);
  341.         for (int i = result1.length - 1; i >= 1; i--) {
  342.             //System.out.println("bytes1.length : " + bytes1.length);
  343.             //System.out.println("bytes2.length : " + bytes2.length);
  344.             //System.out.println("i: " + i);
  345.             byte[] num2 = shift(bytes2, 1);
  346.             byte[] num1 = subarray(bytes1, i - 1, num2.length);
  347.             //System.out.println("bytes1: " + toString(bytes1));
  348.             //System.out.println("num1  : " + toString(num1));
  349.             //System.out.println("num2  : " + toString(num2));
  350.             for (int j = 99; j > 0; j--) {
  351.                 num2 = subtract(num2, bytes2);
  352.                 //System.out.println("j: " + j);
  353.                 //System.out.println("num1: " + toString(num1));
  354.                 //System.out.println("num2: " + toString(num2));
  355.                 if (compareTo(num1, num2) >= 0) {
  356.                     result1[i] = (byte) j;
  357.                     bytes1 = subtract(bytes1, shift(num2, i - 1));
  358.                     break;
  359.                 }
  360.             }
  361.         }
  362.         result[0] = result1;
  363.         bytes1[0] = data1[0];
  364.         result[1] = bytes1;
  365.         return result;
  366.     }
  367.     public LargeInteger divide(LargeInteger... nums) {
  368.         byte[] quotient = this.data;
  369.         for (LargeInteger num : nums) {
  370.             quotient = divide(quotient, num.data)[0];
  371.         }
  372.         return new LargeInteger(quotient);
  373.     }
  374.     public LargeInteger remainder(LargeInteger num) {
  375.         byte[] remainder = divide(this.data, num.data)[1];
  376.         return new LargeInteger(remainder);
  377.     }
  378.     public LargeInteger mod(LargeInteger num) {
  379.         if (num.data == null) {
  380.             throw new NumberFormatException();
  381.         } else if (compareTo(num.data, new byte[2]) <= 0) {
  382.             throw new ArithmeticException();
  383.         }
  384.         byte[] remainder = divide(this.data, num.data)[1];
  385.         //System.out.println("remainder: " + toString(remainder));
  386.         return new LargeInteger(remainder[0] == 0x0 ? remainder : add(num.data, remainder));
  387.     }
  388.     public String toString() {
  389.         return toString(data);
  390.     }
  391.     private static String toString(byte[] data) {
  392.         // 验证数据
  393.         if (data == null || data.length <= 1) {
  394.             return null;
  395.         }
  396.         byte[] bytes = copy(data, -1);
  397.         // 获得数据长度
  398.         int length = bytes.length;
  399.         // 设置输出char array及从低位到高位进行处理的索引
  400.         int index = length + length;
  401.         char[] chars = new char[index--];
  402.         for (int i = 1; i < length; i++) {
  403.             // 获得个位数
  404.             int num1 = bytes[i] % 10;
  405.             // 获得十位数
  406.             int num10 = bytes[i] / 10;
  407.             // 保存个位数的字符
  408.             chars[index--] = (char) (bytes[i] % 10 + '0');
  409.             // 保存十位数的字符
  410.             chars[index--] = (char) (bytes[i] / 10 + '0');
  411.         }
  412.         // 若最高位是'0',截去
  413.         int left = chars[2] == '0' ? 3 : 2;
  414.         // 设置正负符号
  415.         if (bytes[0] == 0x1) {
  416.             chars[--left] = '-';
  417.         }
  418.         // 返回字符串
  419.         return new String(chars, left, chars.length - left);
  420.     }
  421.     public static void main(String[] args) {
  422.         System.out.println("题目要求:如果系统要使用超大整数(超过long的范围),请你设计一个数据结构来存储这种超大型数字以及设计一种算法来实现超大整数的加法运算");
  423.         String str1 = "7363246083486034683046834068860303406834063467340660286027670238403508439035870357057037452750657194361385618374019364013560156019406349215631248654728652462263";
  424.         String str2 = "-890450326502467843206225206846783926523485737101634543894739462923749016316021651061090106189734913864619057083749828964002176309116341493496";
  425.         String str3 = "64068204572572309572305203498204327203957234853207432074230653057026723";
  426.         LargeInteger num1 = new LargeInteger(str1);
  427.         LargeInteger num2 = new LargeInteger(str2);
  428.         LargeInteger num3 = new LargeInteger(str3);
  429.         BigInteger int1 = new BigInteger(str1);
  430.         BigInteger int2 = new BigInteger(str2);
  431.         BigInteger int3 = new BigInteger(str3);
  432.         //System.out.println("num2 : " + num2);
  433.         //System.out.println("shift: " + toString(shift(num2.data, 1)));
  434.         //System.out.println("subarray: " + toString(subarray(num2.data, 1, 5)));
  435.         System.out.println("result1: " + num1);
  436.         System.out.println("result1: " + int1);
  437.         System.out.println("result2: " + num2);
  438.         System.out.println("result2: " + int2);
  439.         System.out.println("negate: " + num1.negate());
  440.         System.out.println("negate: " + int1.negate());
  441.         System.out.println("abs: " + num2.abs());
  442.         System.out.println("abs: " + int2.abs());
  443.         System.out.println("add1: " + num1.add(num2));
  444.         System.out.println("add1: " + int1.add(int2));
  445.         System.out.println("add2: " + num1.add(num2, num2, num2));
  446.         System.out.println("add2: " + int1.add(int2).add(int2).add(int2));
  447.         System.out.println("add3: " + num2.add(num2.negate()));
  448.         System.out.println("add3: " + int2.add(int2.negate()));
  449.         System.out.println("add4: " + num2.add(num3.negate()));
  450.         System.out.println("add4: " + int2.add(int3.negate()));
  451.         System.out.println("add5: " + num2.add(num2));
  452.         System.out.println("add5: " + int2.add(int2));
  453.         System.out.println("subtract4: " + num2.subtract(num3));
  454.         System.out.println("subtract4: " + int2.subtract(int3));
  455.         System.out.println("subtract5: " + (new LargeInteger("10000")).subtract((new LargeInteger("1"))));
  456.         System.out.println("subtract5: " + (new BigInteger("10000")).subtract((new BigInteger("1"))));
  457.         System.out.println("subtract6: " + (new LargeInteger("10000")).subtract((new LargeInteger("9999"))));
  458.         System.out.println("subtract6: " + (new BigInteger("10000")).subtract((new BigInteger("9999"))));
  459.         System.out.println("subtract7: " + (new LargeInteger("1")).subtract((new LargeInteger("10000"))));
  460.         System.out.println("subtract7: " + (new BigInteger("1")).subtract((new BigInteger("10000"))));
  461.         System.out.println("subtract8: " + (new LargeInteger("9999")).subtract((new LargeInteger("10000"))));
  462.         System.out.println("subtract8: " + (new BigInteger("9999")).subtract((new BigInteger("10000"))));
  463.         System.out.println("subtract9: " + (new LargeInteger("-9999")).subtract((new LargeInteger("10000"))));
  464.         System.out.println("subtract9: " + (new BigInteger("-9999")).subtract((new BigInteger("10000"))));
  465.         System.out.println("multiply1: " + num1.multiply(num2));
  466.         System.out.println("multiply1: " + int1.multiply(int2));
  467.         System.out.println("multiply2: " + num1.multiply(num2, num3));
  468.         System.out.println("multiply2: " + int1.multiply(int2).multiply(int3));
  469.         System.out.println("divide5: " + (new LargeInteger("130000")).divide(new LargeInteger("4")));
  470.         System.out.println("divide5: " + (new BigInteger("130000")).divide(new BigInteger("4")));
  471.         System.out.println("divide6: " + (new LargeInteger("-13")).divide(new LargeInteger("4")));
  472.         System.out.println("divide6: " + (new BigInteger("-13")).divide(new BigInteger("4")));
  473.         System.out.println("divide7: " + (new LargeInteger("13")).divide(new LargeInteger("-4")));
  474.         System.out.println("divide7: " + (new BigInteger("13")).divide(new BigInteger("-4")));
  475.         System.out.println("divide8: " + (new LargeInteger("-13")).divide(new LargeInteger("-4")));
  476.         System.out.println("divide8: " + (new BigInteger("-13")).divide(new BigInteger("-4")));
  477.         System.out.println("mod5: " + (new LargeInteger("13")).mod(new LargeInteger("4")));
  478.         System.out.println("mod5: " + (new BigInteger("13")).mod(new BigInteger("4")));
  479.         System.out.println("mod6: " + (new LargeInteger("-13")).mod(new LargeInteger("4")));
  480.         System.out.println("mod6: " + (new BigInteger("-13")).mod(new BigInteger("4")));
  481.         System.out.println("divide1: " + num1.divide(num1));
  482.         System.out.println("divide1: " + int1.divide(int1));
  483.         System.out.println("divide2: " + int1.divide(int1.negate()));
  484.         System.out.println("divide2: " + num1.divide(num1.negate()));
  485.         System.out.println("divide3: " + num2.divide(num2.negate().add(num3)));
  486.         System.out.println("divide3: " + int2.divide(int2.negate().add(int3)));
  487.         System.out.println("divide4: " + num2.divide(num2.negate().subtract(num3)));
  488.         System.out.println("divide4: " + int2.divide(int2.negate().subtract(int3)));
  489.         System.out.println("mod1: " + num2.mod(num3));
  490.         System.out.println("mod1: " + int2.mod(int3));
  491.         System.out.println("mod2: " + num2.negate().mod(num3));
  492.         System.out.println("mod2: " + int2.negate().mod(int3));
  493.     }
  494. }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值