二、大整数减法
1、思路
大整数减法的思路,就是竖式减法a-b,有2种大情况:
- a大于b
- a小于b
第一种情况a>=b,就是逐项相减。如果够减就直接相减;如果本位不够减,寻找下一位借位
- 下一位>0,向下一位借位(
a[i+1]--
),加10到本位上再相减; - 下一位<0,循环查询下下一位(用while语句),找到大于0的那一位,向那一位借位(
a[i+k]--
),加10到本位上再相减,同时把本位下一位到借位位之间的数置为9。 - 如果循环到数组末尾仍然借不到位,那么就是被减数不够减,需要交换被减数和减数,同时计算-(b-a)
第二种情况a小于b,交换对象a和b(这里中间变量需用对象变量bigNum tmp
),然后算-(b-a)
2、 算法
运用数组存储两个操作数,先判断情况,再右对齐逐位相减
void operator- (bigNum & result,bigNum & b)
{
int length1=result.len,length2=b.len;
bigNum tmp1,tmp2;
tmp1=result;
tmp2=b; /*保护现场*/
if(length1>=length2){ /*情况1:如果a>b或者a足够减b*/ /*注意还有区分虽然长度一样,但实际借不到位的情况,如2-3*/
for( int i = 0;i < MAX_LEN+10 ; i ++ )
{
if(result.sInt[i] >= b.sInt[i]){/*如果够减*/
result.sInt[i] -= b.sInt[i]; //逐位相减
continue;
}
else{ /*不够减*/
if( result.sInt[i+1] > 0 ) //如果下一位够减
{ //就借位
result.sInt[i] += 10; //借位
result.sInt[i] -= b.sInt[i]; //逐位相减
result.sInt[i+1]--;
}
else{ /*如果下一位不够减,试探下下位 */
int k=1;
while(result.sInt[i+k] == 0)
k++;
if(i+k>= MAX_LEN+10){/*注意还有区分虽然长度一样,但实际借不到位的情况,如2-3*/
result=tmp2; /*情况3:a不足以减b,计算-(b-a)*/
b=tmp1; /*恢复现场*/
cannotSub=1; /*布尔变量,标记被减数小于减数*/
result-b; /*恢复现场时已经交换了位置*/
if(o=='-') /*除法也会调用减号函数,只有在减号下才打印负号*/
cout<<"-";
break;
}
if( result.sInt[i+k] > 0 ) //如果下下位够减
{ //就借位
result.sInt[i] += 10; //借位
result.sInt[i] -= b.sInt[i]; //相减
result.sInt[i+k]--;
for(int j=i+1;j<=k+i-1;j++){
result.sInt[j]=9; //并且中间的0全部变为9
}
}
}
}
}
}
if(length1<length2){ /*情况2:如果a<b,结果为-(b-a) */
bigNum tmp; /*简洁*/
tmp=result;
result=b;
b=tmp;
result-b;
if(o=='-')
cout<<"-";
}
result.len=0;
for(int i=MAX_LEN+9;i>=0;i--){
if(result.sInt[i]!=0){
result.len=i+1; /*除法要用到长度,数组长度更新*/
break;
}
}
}