接昨天的《java大数算法完成五则运算之类基础》这篇文章,今天就先说说加减,毕竟比较简单,就丢一起了。
首先先说说算法思路,就是用最简单的最实用的,我们平时做加减的方法!数字右对齐,往左递推,依次运算,进位借位即可
废话不多说,直接上代码:
关于类中的其它方法和属性详看java大数算法完成五则运算之类基础,这里就不再讲了
public BigNum add(BigNum add) throws Exception {
int addnum[] = add.NUM;//保存加的数组
char newNumSign = 0;//保存和的符号
int newNum[] = null;//保存和的数组
if (SIGN == add.SIGN) {//同正负号时,符号不变一致
newNumSign = SIGN;
newNum = addnum(NUM, addnum);//调用加法
} else {//异号时,谁的绝对值比较大就用谁的符号
if (intArrCompaerTo(NUM, addnum) == 1) {
newNumSign = SIGN;
} else {
newNumSign = add.SIGN;
}
newNum = subNum(NUM, addnum);//调用减法
}
BigNum b = new BigNum(newNum, newNumSign);
return b;
}
private int[] addnum(int a[], int b[]) {
int p1;//较大大数数组运算指针,指针均从右往左
int p2;//较小大数数组运算指针
int num[] = null;//和数组
int p3;//和数组指针
if (a.length == b.length) {//当两个大数位数一样时
p1 = p2 = a.length - 1;
num = new int[a.length + 1];//加一是因为有可能会多进一位
p3 = a.length;
for (; p1 > -1; p1--) {
int temp = 0;//保存每位之和
temp = a[p1] + b[p2--];
if (temp > 9) {//当前位之和大于9要进位
num[p3--] = temp % 10;//加上个位
num[p3] = temp / 10;//进位
} else {
num[p3--] = temp;
}
}
} else {//两个大数位数不相同时
int tempNum[] = a;//用临时数组保存当前对象的大数
if (a.length < b.length) {//tempNum恒存放大的大数,add存放小的大数
tempNum = b;
b = a;
}
p1 = tempNum.length - 1;
p2 = b.length - 1;
num = new int[tempNum.length + 1];
p3 = tempNum.length;
for (; p1 > -1; p1--) {
int temp = 0;//保存每位的和
if (p2 < 0) {//较小数组可能会先加完
temp = tempNum[p1];
} else {
temp = tempNum[p1] + b[p2--];
}
if (temp > 9) {//进位
num[p3--] = temp % 10;//加上个位
num[p3] = temp / 10;//进位
} else {
num[p3--] = temp;
}
}
}
return num;
}
加法的代码就是这些,没什么很难的,就是稍微有点绕,要根据符号的不同来选择做加法还是减法,要根据位数不一样来写不同的实现方法,减法也是类似。
接下来是减法:
public BigNum sub(BigNum sub) throws Exception {
int subNum[] = sub.NUM;//减数
char newNumSign = 0;//保存差的符号
int newNum[] = null;//保存差的数组
if (SIGN == sub.SIGN) {//符号相同时
switch (compareTo(sub)) {//比较大小
case -1://小于
newNumSign = '-';
break;
case 0://等于
newNumSign = '+';
newNum = new int[1];
newNum[0] = 0;
break;
case 1://大于
newNumSign = '+';
break;
}
newNum = subNum(NUM, sub.NUM);//调用减法
} else {//异号
if (SIGN == '+') {
newNumSign = '+';
} else {
newNumSign = '-';
}
newNum = addnum(NUM, sub.NUM);//调用加法
}
BigNum b = new BigNum(newNum, newNumSign);
return b;
}
private int[] subNum(int a[], int b[]) {
int p1 = 0;//较大大数数组运算指针,指针均从右往左
int p2 = 0;//较小大数数组运算指针
int num[] = null;//余数组
int big[] = a;//保存较大数组,b保存较小数组
int p3 = 0;//余数组指针
switch (intArrCompaerTo(a, b)) {//比较两个数组大小,使得big恒保存较大数组
case -1://a小于b
big = b;
b = a;
p1 = big.length - 1;
p2 = b.length - 1;
num = new int[big.length];
p3 = num.length - 1;
break;
case 0://a=b,结果为零,直接返回
num = new int[1];
num[0] = 0;
return num;
case 1://a大于b
p1 = big.length - 1;
p2 = b.length - 1;
num = new int[big.length];
p3 = num.length - 1;
break;
}
for (; p1 > -1; p1--) {//以大数组的长度来从右往左运算
if (p2 < 0) {//当大数组还有数字而小数组没有后执行
if (big[p1] < 0) {//如果当前位小于0,即在上一次循环中被借了一位,再往前借一次
big[p1 - 1] -= 1;
big[p1] += 10;
}
num[p3--] = big[p1];
} else {//小数组还有数字
if (big[p1] < b[p2]) {//大数组的当前位小于小数组的当前位时借位
big[p1 - 1] -= 1;
big[p1] += 10;
}
num[p3--] = big[p1] - b[p2--];
}
}
return num;
}