复习一道老题目,不使用BigInteger,手动计算长整数的加减法(字符串表示,可带符号)。

/**
 * Created by gj21798 on 2019/11/13
 */
public class CalcStringNumber {
    public static void main(String[] args) {
        assert "2468".equals(add("1234", "1234"));
        assert "10470".equals(add("5235", "5235"));
        assert "0".equals(add("-1234", "1234"));
        assert "0".equals(add("1234", "-1234"));
        assert "-1".equals(add("1234", "-1235"));
        assert "1".equals(add("-1234", "1235"));

        assert "-2469".equals(sub("-1234", "1235"));
        assert "-1".equals(sub("1234", "1235"));
        assert "2469".equals(sub("1234", "-1235"));
        assert "0".equals(sub("-1234", "-1234"));
        assert "-1234".equals(sub("0", "1234"));
        assert "1234".equals(sub("0", "-1234"));
    }

    /**
     * 带符号相加
     */
    private static String add(String s1, String s2) {
        boolean isPos1 = s1.charAt(0) != '-';
        boolean isPos2 = s2.charAt(0) != '-';

        //都为非负数,直接无符号相加
        if (isPos1 && isPos2) return addPositive(s1, s2);
        //都为负数,无符号相加再取反
        if (!isPos1 && !isPos2) return '-' + addPositive(s1.substring(1), s2.substring(1));
        //1正,2负,去掉符号比较字符串,根据比较结果做绝对值加减,并赋相应符号
        if (isPos1) {
            int r = s1.compareTo(s2.substring(1));
            if (r > 0) return subPositive(s1, s2.substring(1));
            else if (r == 0) return "0";
            else return '-' + subPositive(s2.substring(1), s1);
        }

        //1负,2正,去掉符号比较字符串,根据比较结果做绝对值加减,并赋相应符号
        int r = s1.substring(1).compareTo(s2);
        if (r > 0) return '-' + subPositive(s1.substring(1), s2);
        else if (r == 0) return "0";
        else return subPositive(s2, s1.substring(1));
    }

    /**
     * 带符号相减
     */
    private static String sub(String s1, String s2) {
        boolean isPos1 = s1.charAt(0) != '-';
        boolean isPos2 = s2.charAt(0) != '-';

        //1正,2负,去掉负号,做正整数相加
        if (isPos1 && !isPos2) {
            return addPositive(s1, s2.substring(1));
        } else if (!isPos1 && isPos2) {
            //1负,2正,绝对值相加再取负号
            return '-' + addPositive(s1.substring(1), s2);
        }

        //均为正,比较字符串,根据比较结果做绝对值加减,并赋相应符号
        if (isPos1 && isPos2) {
            int r = s1.compareTo(s2);
            if (r > 0) return subPositive(s1, s2);
            else if (r == 0) return "0";
            else return '-' + subPositive(s2, s1);
        }

        //均为负,比较字符串,根据比较结果做绝对值加减,并赋相应符号
        int r = s1.compareTo(s2);
        if (r > 0) return '-' + subPositive(s2, s1);
        else if (r == 0) return "0";
        else return subPositive(s1, s2);
    }

    /**
     * 无符号相加
     */
    private static String addPositive(String s1, String s2) {
        int len1 = s1.length();
        int len2 = s2.length();
        int len = Math.max(len1, len2);

        //暂存计算结果
        int[] result = new int[len];
        //进位符号,为1表示有进位
        int carry = 0;
        for (int i = len - 1; i >= 0; i--) {
            int a1 = i < len1 ? s1.charAt(i) - '0' : 0;
            int a2 = i < len2 ? s2.charAt(i) - '0' : 0;
            //带进位相加
            int a = a1 + a2 + carry;
            result[i] = a % 10;
            //判断当前计算是否产生进位
            carry = a > 9 ? 1 : 0;
        }

        StringBuilder sb = new StringBuilder();
        //有进位则头部加1
        if (carry == 1) sb.append('1');
        for (int i = 0; i < len; i++) sb.append(result[i]);
        return sb.toString();
    }

    /**
     * 无符号相减
     */
    private static String subPositive(String s1, String s2) {
        int len1 = s1.length();
        int len2 = s2.length();
        int len = Math.max(len1, len2);

        //暂存计算结果
        int[] result = new int[len];
        int carry = 0;
        for (int i = len - 1; i >= 0; i--) {
            int a1 = i < len1 ? s1.charAt(i) - '0' : 0;
            int a2 = i < len2 ? s2.charAt(i) - '0' : 0;
            //判断低一位计算是否产生借位,如有借位则减1
            if (carry == 1) a1--;
            if (a1 >= a2) {
                //不需要借位,直接相减
                carry = 0;
                result[i] = a1 - a2;
            } else {
                //需要借位,置借位标识并相减
                carry = 1;
                result[i] = a1 + 10 - a2;
            }
        }

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < len; i++) sb.append(result[i]);
        return trimZero(sb.toString());
    }

    /**
     * 移除0开头的数字字符
     */
    private static String trimZero(String text) {
        StringBuilder sb = new StringBuilder();
        boolean needIgnore = true;
        for (char c : text.toCharArray()) {
            if (needIgnore && c == '0') continue;
            needIgnore = false;
            sb.append(c);
        }
        return sb.toString();
    }
}

  

12-28 11:02