Skip to content

字符串相减(大数相减)

约 483 字大约 2 分钟

2025-03-01

给定两个字符串形式的非负整数 num1 和num2 ,计算它们的差。

注意:

  1. num1 和num2 都只会包含数字 0-9
  2. num1 和num2 都不包含任何前导零
  3. 你不能使用任何內建 BigInteger 库

('0' + val) 将这个整数值转换为对应的字符形式。例如:

  • val = 0 时,'0' + 0 = '0'
  • val = 1 时,'0' + 1 = '1'
  • val = 9 时,'0' + 9 = '9'

这是因为 ASCII 码中,字符 '0' 的值是 48,字符 '1' 是 49,依此类推。

(char) ('0' + val)int 类型的结果强制转换为 char 类型,使其成为一个字符。

class Solution {
    // 执行基数为10的减法运算
    public static String sub(String a, String b) {
        StringBuilder res = new StringBuilder();
        int borrow = 0;
        int i = a.length() - 1, j = b.length() - 1;
        
        // 逐位计算减法
        // 对于加法,结束条件还要加一个进位不为零
        while (i >= 0 || j >= 0) {
            int x = i >= 0 ? a.charAt(i) - '0' : 0;
            int y = j >= 0 ? b.charAt(j) - '0' : 0;
            
            // 重点。
            int val = (x - borrow - y + 10) % 10;
            // 注意必须要+'0',假设val=2,'0'的ASCII值是48,我们要计算ASCII值,然后转成字符。
            res.append((char) ('0' + val));
            
            // 重点。
            borrow = x - borrow - y < 0 ? 1 : 0;
            i--;
            j--;
        }
        
        // 反转结果字符串
        res.reverse();
        
        // 删除前导零。循环条件是 res.length() - 1 是为防止 "0000" 的情况。只需检查[0,res.length-2],不需要检查最后一个是否为零,就是它是零也无所谓。
        int pos;
        for (pos = 0; pos < res.length() - 1; pos++) {
            if (res.charAt(pos) != '0') break;
        }
        
        return res.substring(pos);
    }

    // 比较两个字符串大小
    public static boolean cmp(String a, String b) {
        if (a.length() == b.length()) return a.compareTo(b) < 0;
        return a.length() < b.length();
    }

    // 执行两个基数为10的字符串的减法运算
    public static String subStrings(String num1, String num2) {
        String res;
        // 如果nums1<num2,则先用num2减去num1,再在结果前加个负号。
        if (cmp(num1, num2)) {
            res = sub(num2, num1);
            // 重点。
            if (!res.equals("0")) res = "-" + res;
        } else {
            res = sub(num1, num2);
        }
        return res;
    }
}