在计算机中,通常用int,long来存储整形数字,但由于空间问题,当数字过大时,long也存储不了。因此当需要高精度计算大数的时候,该怎样处理呢?(不利用大数类)

现目前我有三条思路

  1. 模拟传统的人工乘法
  2. 竖式优化的乘法
  3. 分而治之
  4. 利用BigInteger类

1. 传统的人工乘法

思路:将乘数的每一位与被乘数相乘,得到的结果后面追加适当的0元素,再将所有的结果相加即可

此思路要用到额外的两个方法

  1. 将两个大数相加
  2. 一位数乘以多位数(包含一位数的情况)

代码如下:



/** 415. 字符串相加 */
public String addStrings(String num1, String num2) {
    int len1 = num1.length(), len2 = num2.length(), temp = 0;
    int max = Math.max(len1, len2);
    StringBuilder stringBuilder = new StringBuilder();
    for (int i = 0; i < max; ++ i) {
        temp += i < len1 ? num1.charAt(len1 - 1 - i) - '0' : 0;
        temp += i < len2 ? num2.charAt(len2 - 1 - i) - '0': 0;
        stringBuilder.append(temp % 10);
        temp /= 10;
    }
    if(temp != 0) stringBuilder.append(temp);
    return stringBuilder.reverse().toString();
}

/** 43. 字符串相乘 */
public String multiply(String num1, String num2) {
    if("0".equals(num1) || "0".equals(num2))  return "0";
    int len2 = num2.length();
    String string = "";
    for (int i = 0; i < len2; ++ i) {
        // 追加i个0
        StringBuilder stringBuilder = new StringBuilder();
        for (int j = 0; j < i; j++) {
            stringBuilder.append(0);
        }
        string = addStrings(string, mul(num2.charAt(len2 - 1 - i), num1) + stringBuilder);
    }
    return string;
}

/** 一位数乘以多位数 */
public String mul(char ch, String string) {
    int len = string.length();
    int num = ch - 48, carry = 0;
    StringBuilder stringBuilder = new StringBuilder();
    for (int i = 0; i < len; i++) {
        carry += num * (int)(string.charAt(len - 1 - i) - '0');
        stringBuilder.append(carry % 10);
        carry /= 10;
    }
    if(carry != 0) stringBuilder.append(carry);
    return stringBuilder.reverse().toString();
}

 

2. 利用竖式优化

注意两个点:

  1. 一个长度为n的和一个长度为m的数相乘,其结果的长度最多为n+m(不信你试试)
  2. num1[i]和num2[j]相乘一定不超过两位数。第一位位于arr[i + j] 第二位位于arr[i + j + 1]


public String multiply(String num1, String num2) {
    if("0".equals(num1) || "0".equals(num2)) return "0";
    int len1 = num1.length(), len2 = num2.length(), temp;
    int[] arr = new int[len1 + len2];
    for (int i = len1 - 1; i >= 0; -- i) {
        int n1 = num1.charAt(i) - 48;
        for (int j = num2.length() - 1; j >= 0; -- j) {
            int n2 = num2.charAt(j) - 48;
            temp = arr[i + j + 1] + n1 * n2;
            arr[i + j + 1] = temp % 10;
            arr[i + j] += temp / 10;
        }
    }
    StringBuilder stringBuilder = new StringBuilder();
    int i = arr[0] == 0 ? 1 : 0;
    while (i < arr.length) {
        stringBuilder.append(arr[i ++]);
    }
    return stringBuilder.toString();
}

 

3. 分而治之

算法思路:

 

代码实现:



/** 44. 分治算法 */
public String multiply2(String num1, String num2) {
    if(num1.length() == 1 || num2.length() == 1) return String.valueOf(Integer.valueOf(num1) * Integer.valueOf(num2));
    // 拆分的长度
    int middle = Math.max(num1.length(), num2.length()) / 2;
    // 拆分出a b c d
    String a = num1.substring(0, num1.length() - middle);
    String b = num1.substring(num1.length() - middle);
    String c = num2.substring(0, num2.length() - middle);
    String d = num2.substring(num2.length() - middle);
    // 计算a * c,b * d,和b * c + a * d
    String ac = multiply2(a, c);
    String bd = multiply2(b, d);
    // b * c + a * d = (a + b) * (c + d) - a * c - b * d
    String bcad = subStract(subStract(multiply2(addStrings(a, b), addStrings(c, d)), ac), bd);
    StringBuilder stringBuilder = new StringBuilder();
    for (int i = 0; i < 2 * middle; ++ i) {
        stringBuilder.append('0');
    }
    return addStrings(bd, addStrings(ac + stringBuilder.toString(), bcad + stringBuilder.substring(middle)));
}


/** 415. 字符串相加 */
public String addStrings(String num1, String num2) {
    int len1 = num1.length(), len2 = num2.length(), temp = 0;
    int max = Math.max(len1, len2);
    StringBuilder stringBuilder = new StringBuilder();
    for (int i = 0; i < max; ++ i) {
        temp += i < len1 ? num1.charAt(len1 - 1 - i) - '0' : 0;
        temp += i < len2 ? num2.charAt(len2 - 1 - i) - '0': 0;
        stringBuilder.append(temp % 10);
        temp /= 10;
    }
    if(temp != 0) stringBuilder.append(temp);
    return stringBuilder.reverse().toString();
}


/** 字符串的减法 */
public String subStract(String string1, String string2) {
    int len1 = string1.length(), len2 = string2.length(), judge;
    if(len1 > len2) {
        judge = 1;
    }else if (len1 < len2) {
        judge = -1;
    }else {
        judge = string1.compareTo(string2);
    }
    if(judge < 0)  return "-" + subStract(string2, string1);
    else if (judge == 0) return "0";
    int temp = 0;
    int max = Math.max(len1, len2);
    StringBuilder stringBuilder = new StringBuilder();
    for (int i = 0; i < max; i++) {
        int a = i < len1 ? string1.charAt(len1 - 1 - i) - '0' : 0;
        int b = i < len2 ? string2.charAt(len2 - 1 - i) - '0' : 0;
        int num = a - temp - b;
        if(num < 0) {
            num = 10 + a - b - temp;
            temp = 1;
        }else {
            temp = 0;
        }
        stringBuilder.append(num);
    }
    // 去掉多余的0
    for (int i = stringBuilder.length() - 1; i >= 0; -- i) {
        if(stringBuilder.charAt(i) != '0') {
            break;
        }
        stringBuilder.deleteCharAt(i);
    }
    return stringBuilder.reverse().toString();
}

 

4. 用BigInteger类

 

 

您必须 登录 才能发表评论