复习一道老题目,不使用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(); } }