package top.chitucao.algorithm.Math;
import java.util.Objects;
/**
* @author chitucao
* @since 2022/11/23 10:10
* 大数加法,包括正负的情况
* 参考 https://developer.aliyun.com/article/1057265
*/
public class LargeNumber {
public static void main(String[] args) {
String num1 = "123";
String num2 = "-456";
System.out.println(new LargeNumber().add(num1, num2));
}
public String add(String num1, String num2) {
boolean isPositiveNum1 = num1.charAt(0) != '-';
boolean isPositiveNum2 = num2.charAt(0) != '-';
if (isPositiveNum1 && isPositiveNum2) {
return doAdd(num1, num2);
} else if (!isPositiveNum1 && !isPositiveNum2) {
return negate(doAdd(num1.substring(1), num2.substring(1)));
} else if (isPositiveNum1 && !isPositiveNum2) {
return doSub(num1, num2.substring(1));
} else {
return doSub(num2, num1.substring(1));
}
}
// 相加
private String doAdd(String num1, String num2) {
int len1 = num1.length() - 1;
int len2 = num2.length() - 1;
int carry = 0;
StringBuilder sb = new StringBuilder();
while (len1 >= 0 || len2 >= 0) {
int n1 = len1 >= 0 ? num1.charAt(len1--) - '0' : 0;
int n2 = len2 >= 0 ? num2.charAt(len2--) - '0' : 0;
int sum = n1 + n2 + carry;
carry = sum / 10;
sb.append(sum % 10);
}
// 这里注意进位
if (carry > 0) {
sb.append(1);
}
return sb.reverse().toString();
}
// 相减
private String doSub(String num1, String num2) {
if (!compare(num1, num2)) {
return negate(doSub(num2, num1)); // 保证num1>=num2
}
int len1 = num1.length() - 1;
int len2 = num2.length() - 1;
int borrow = 0;
StringBuilder sb = new StringBuilder();
while (len1 >= 0 || len2 >= 0) {
int n1 = len1 >= 0 ? num1.charAt(len1--) - '0' : 0;
int n2 = len2 >= 0 ? num2.charAt(len2--) - '0' : 0;
int num = n1 - n2 - borrow;
// 借位
if (num < 0) {
borrow = 1;
num += 10;
}
sb.append(num);
}
// 反转后去掉前导0 22-14=08
sb.reverse();
int idx = 0;
while (idx < sb.length() && sb.charAt(idx) == '0') {
idx++;
}
// 等于0的特殊情况
if (idx == sb.length()) {
return "0";
}
return sb.substring(idx);
}
// num1是否大于等于num2
private boolean compare(String num1, String num2) {
if (num1.length() == num2.length()) {
// return num1.compareTo(num2) >= 0;
for (int i = 0; i < num1.length(); i++) {
if (num1.charAt(i) < num2.charAt(i)) {
return false;
}
}
return true;
} else {
return num1.length() > num2.length();
}
}
// 反转正负情况
private String negate(String num) {
if (num.charAt(0) == '-') {
return num.substring(1);
} else if (Objects.equals(num, "0")) {
return num;
} else {
return "-" + num;
}
}
}