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