Java计算长整数加减(字符串表示)
复习一道老题目,不使用BigInteger,手动计算长整数的加减法(字符串表示,可带符号)。
1 /** 2 * Created by areful on 2019/11/13 3 */ 4 public class CalcStringNumber { 5 private static final String REG_EXP_NUMBER = "0|(-?[1-9]+[0-9]*)"; 6 private static final String REG_EXP_NON_NEGATIVE_NUMBER = "0|([1-9]+[0-9]*)"; 7 8 /** 9 * 带符号相加 10 */ 11 private static String add(String s1, String s2) { 12 assert s1.matches(REG_EXP_NUMBER) && s2.matches(REG_EXP_NUMBER); 13 14 boolean isPos1 = s1.charAt(0) != '-'; 15 boolean isPos2 = s2.charAt(0) != '-'; 16 17 if (isPos1 && isPos2) { 18 //都为非负数,直接无符号相加 19 return addPositive(s1, s2); 20 } else if (!isPos1 && !isPos2) { 21 //都为负数,无符号相加再取反 22 return '-' + addPositive(s1.substring(1), s2.substring(1)); 23 } else if (isPos1) { 24 //1正,2负,比较字符串长度 25 if (s1.length() > s2.substring(1).length()) { 26 //1比2长,正号 27 return subPositive(s1, s2.substring(1)); 28 } else if (s1.length() < s2.substring(1).length()) { 29 //1比2短,负号 30 return '-' + subPositive(s1, s2.substring(1)); 31 } else { 32 //长度相同,去掉符号比较字符串,根据比较结果做绝对值加减,并赋相应符号 33 int r = s1.compareTo(s2.substring(1)); 34 if (r > 0) return subPositive(s1, s2.substring(1)); 35 else if (r == 0) return "0"; 36 else return '-' + subPositive(s2.substring(1), s1); 37 } 38 } else { 39 //1负,2正,比较字符串长度 40 if (s1.substring(1).length() > s2.length()) { 41 //1比2长,负号 42 return '-' + subPositive(s1.substring(1), s2); 43 } else if (s1.substring(1).length() < s2.length()) { 44 //1比2短,正号 45 return subPositive(s2, s1.substring(1)); 46 } else { 47 //长度相同,去掉符号比较字符串,根据比较结果做绝对值加减,并赋相应符号 48 int r = s1.substring(1).compareTo(s2); 49 if (r > 0) return '-' + subPositive(s1.substring(1), s2); 50 else if (r == 0) return "0"; 51 else return subPositive(s2, s1.substring(1)); 52 } 53 } 54 } 55 56 /** 57 * 带符号相减 58 */ 59 private static String sub(String s1, String s2) { 60 assert s1.matches(REG_EXP_NUMBER) && s2.matches(REG_EXP_NUMBER); 61 62 boolean isPos1 = s1.charAt(0) != '-'; 63 boolean isPos2 = s2.charAt(0) != '-'; 64 65 if (isPos1 && !isPos2) { 66 //1正,2负,去掉负号,做正整数相加 67 return addPositive(s1, s2.substring(1)); 68 } else if (!isPos1 && isPos2) { 69 //1负,2正,绝对值相加再取负号 70 return '-' + addPositive(s1.substring(1), s2); 71 } else if (isPos1) { 72 //均为正,比较字符串长度 73 if (s1.length() > s2.length()) { 74 //1比2长,正号 75 return subPositive(s1, s2); 76 } else if (s1.length() < s2.length()) { 77 //1比2短,负号 78 return '-' + subPositive(s2, s1); 79 } else { 80 //长度相同,比较字符串,根据比较结果做绝对值加减,并赋相应符号 81 int r = s1.compareTo(s2); 82 if (r > 0) return subPositive(s1, s2); 83 else if (r == 0) return "0"; 84 else return '-' + subPositive(s2, s1); 85 } 86 } else { 87 //均为负,比较字符串长度 88 if (s1.length() > s2.length()) { 89 //1比2长,负号 90 return '-' + subPositive(s1.substring(1), s2.substring(1)); 91 } else if (s1.length() < s2.length()) { 92 //1比2短,正号 93 return subPositive(s2.substring(1), s1.substring(1)); 94 } else { 95 //长度相同,比较字符串,根据比较结果做绝对值加减,并赋相应符号 96 int r = s1.compareTo(s2); 97 if (r > 0) return '-' + subPositive(s1.substring(1), s2.substring(1)); 98 else if (r == 0) return "0"; 99 else return subPositive(s1.substring(1), s2.substring(1)); 100 } 101 } 102 } 103 104 /** 105 * 无符号相加 106 */ 107 private static String addPositive(String s1, String s2) { 108 assert s1.matches(REG_EXP_NON_NEGATIVE_NUMBER) && s2.matches(REG_EXP_NON_NEGATIVE_NUMBER); 109 110 int len1 = s1.length(); 111 int len2 = s2.length(); 112 int len = Math.max(len1, len2); 113 114 //暂存计算结果 115 int[] result = new int[len]; 116 //进位符号,为1表示有进位 117 int carry = 0; 118 for (int i = 0; i < len; i++) { 119 int a1 = i < len1 ? s1.charAt(len1 - 1 - i) - '0' : 0; 120 int a2 = i < len2 ? s2.charAt(len2 - 1 - i) - '0' : 0; 121 //带进位相加 122 int a = a1 + a2 + carry; 123 result[len - 1 - i] = a % 10; 124 //判断当前计算是否产生进位 125 carry = a > 9 ? 1 : 0; 126 } 127 128 StringBuilder sb = new StringBuilder(); 129 //有进位则头部加1 130 if (carry == 1) sb.append('1'); 131 for (int i = 0; i < len; i++) sb.append(result[i]); 132 return trimZero(sb.toString()); 133 } 134 135 /** 136 * 无符号相减 137 */ 138 private static String subPositive(String s1, String s2) { 139 assert s1.matches(REG_EXP_NON_NEGATIVE_NUMBER) && s2.matches(REG_EXP_NON_NEGATIVE_NUMBER); 140 if (s1.equals(s2)) return "0"; 141 142 int len1 = s1.length(); 143 int len2 = s2.length(); 144 int len = Math.max(len1, len2); 145 146 //暂存计算结果 147 int[] result = new int[len]; 148 int carry = 0; 149 for (int i = 0; i < len; i++) { 150 int a1 = i < len1 ? s1.charAt(len1 - 1 - i) - '0' : 0; 151 int a2 = i < len2 ? s2.charAt(len2 - 1 - i) - '0' : 0; 152 //判断低一位计算是否产生借位,如有借位则减1 153 if (carry == 1) a1--; 154 if (a1 >= a2) { 155 //不需要借位,直接相减 156 carry = 0; 157 result[len - 1 - i] = a1 - a2; 158 } else { 159 //需要借位,置借位标识并相减 160 carry = 1; 161 result[len - 1 - i] = a1 + 10 - a2; 162 } 163 } 164 165 StringBuilder sb = new StringBuilder(); 166 for (int i = 0; i < len; i++) sb.append(result[i]); 167 return trimZero(sb.toString()); 168 } 169 170 /** 171 * 移除0开头的数字字符 172 */ 173 private static String trimZero(String text) { 174 StringBuilder sb = new StringBuilder(); 175 boolean needIgnore = true; 176 for (char c : text.toCharArray()) { 177 if (needIgnore && c == '0') continue; 178 needIgnore = false; 179 sb.append(c); 180 } 181 if (sb.length() == 0) sb.append('0'); 182 return sb.toString(); 183 } 184 185 public static void main(String[] args) { 186 assert "0".equals(add("0", "0")); 187 assert "-24".equals(add("-15", "-9")); 188 assert "-6".equals(add("-15", "9")); 189 assert "6".equals(add("15", "-9")); 190 assert "24".equals(add("15", "9")); 191 assert "2468".equals(add("1234", "1234")); 192 assert "10470".equals(add("5235", "5235")); 193 assert "0".equals(add("-1234", "1234")); 194 assert "0".equals(add("1234", "-1234")); 195 assert "-1".equals(add("1234", "-1235")); 196 assert "1".equals(add("-1234", "1235")); 197 assert "6".equals(add("15", "-9")); 198 assert "-6".equals(add("-15", "9")); 199 assert "24700000000000000000000000000000000000000000000000".equals( 200 add("12350000000000000000000000000000000000000000000000", "12350000000000000000000000000000000000000000000000")); 201 202 assert "0".equals(sub("0", "0")); 203 assert "6".equals(sub("-9", "-15")); 204 assert "-24".equals(sub("-9", "15")); 205 assert "24".equals(sub("9", "-15")); 206 assert "-6".equals(sub("9", "15")); 207 assert "6".equals(sub("15", "9")); 208 assert "-6".equals(sub("-15", "-9")); 209 assert "-24".equals(sub("-15", "9")); 210 assert "24".equals(sub("15", "-9")); 211 assert "6".equals(sub("15", "9")); 212 assert "-2469".equals(sub("-1234", "1235")); 213 assert "-1".equals(sub("1234", "1235")); 214 assert "0".equals(sub("1234", "1234")); 215 assert "0".equals(sub("-1234", "-1234")); 216 assert "-1234".equals(sub("0", "1234")); 217 assert "1234".equals(sub("0", "-1234")); 218 assert "1234".equals(sub("1234", "0")); 219 assert "24700000000000000000000000000000000000000000000000".equals( 220 sub("12350000000000000000000000000000000000000000000000", "-12350000000000000000000000000000000000000000000000")); 221 } 222 }