您的位置:首页 > 编程语言 > C语言/C++

C++实现大数的减法

2014-09-19 23:11 387 查看
减法稍微有一点复杂,因为会处理负数,而我们所用的是字符串的形式来保存数字也是为这一点。否则用整型或其它类型时,则表示处理、保存时会相当复杂。算法也是从低位开始减。先要判断减数和被减数那一个位数长,减数位数长是正常减;被减数位数长,则被减数减减数,最后还要加上负号;两数位数长度相等时,最好比那一个数字大,否则负号处理会很繁琐;处理每一项时要,如果前一位相减有借位,就先减去上一位的借位,无则不减,再去判断是否能够减开被减数,如果减不开,就要借位后再去减,同时置借位为1,否则置借位为0。



//算法也是从低位开始减。先要判断减数和被减数那一个位数长,减数位数长是正常减;被减数位数长,则被减数减减数,最后还要加上负号;

//两数位数长度相等时,最好比那一个数字大,否则负号处理会很繁琐;处理每一项时要,如果前一位相减有借位,就先减去上一位的借位,无则不减,再去判断是否能够减开被减数,

//如果减不开,就要借位后再去减,同时置借位为1,否则置借位为0

#include<iostream>

#include<cstring>//strlen是操纵c风格字符串的标准库函数,因此要有头文件#include<cstring>

using namespace std;

bool Isequal=false;

//strcmp(s1,s2),比较两个字符串是s1,s2是否相同,如果s1等于s2,则返回0,如果s1小于s2则返回负数,如果s1大于s2则返回正数

//要定义一个比较函数,比较输入的两个数的大小,但是不能完全依靠strcmp函数,因为它有些问题,比如123456,与128比会得出128大,因为它是从数组第一位开始比较的,8大于3。

//另外写一个比较函数

int compare(char* num1,char* num2)

{
int num1length=strlen(num1);
int num2length=strlen(num2);
if(num1length>num2length) //长度不等的时候,哪个长,哪个数就大
return 1;//表示num1大于num2
else if(num1length<num2length)
return -1;//表示num1小于num2
else //两者长度相等,则用strcmp来比较大小
{
if(strcmp(num1,num2)==0)
return 0;//表示两个大数是相等的
else if(strcmp(num1,num2)>0)
return 1;//num1大于num2
else
return -1;//num1小于num2
}

}

//没有考虑相减的数中存在负数的情况,只考虑了相减的两数都是正数的情况

void Minus(char* num1,char* num2,char* result,int num1length,int num2length,int resultindex)

{
int k=compare(num1,num2);
if(k==0)//两数相等
{
Isequal=true;
return;
}
if(k==1)//num1大于num2
{
int nminus=0;//保存减法的结果
int flag=0;//标志发生了借位 
while(num1length>=0&&num2length>=0)
{
if(num1[num1length]>=(num2[num2length]+flag))
{
nminus=(num1[num1length--]-'0')-(num2[num2length--]-'0')-flag;
flag=0;//注意这里必须更新flag,因为没有向前面借位,所以flag更新为0
}
if(num1[num1length]<(num2[num2length]+flag))
{
nminus=(num1[num1length--]-'0')-(num2[num2length--]-'0')+10-flag;
flag=1;
}
result[resultindex--]=nminus+'0';
}
if(num1length<0)
{
while(num2length>=0)
{
if(num2[num2length]>=flag)
{
nminus=num2[num2length--]-'0'-flag;
flag=0;
}
else
{
nminus=num2[num2length--]-'0'+10-flag;
flag=1;
}
result[resultindex--]=nminus+'0';
}
}
if(num2length<0)
{
while(num1length>=0)
{
if(num1[num1length]>=flag)
{
nminus=num1[num1length--]-'0'-flag;
flag=0;
}
else
{
nminus=num1[num1length--]-'0'-flag+10;
flag=1;
}
result[resultindex--]=nminus+'0';
}
}
}

if(k==-1)//num2大于num1,故最后的时候还要保存一个负号
{
int nminus=0;//保存减法的结果
int flag=0;//标志借位
while(num1length>=0&&num2length>=0)
{
if(num2[num2length]>=(num1[num1length]+flag))
{
nminus=(num2[num2length--]-'0')-(num1[num1length--]-'0')-flag;
flag=0;
}
if(num2[num2length]<(num1[num1length]+flag))
{
nminus=(num2[num2length--]-'0')-(num1[num1length--]-'0')+10-flag;
flag=1;//更新flag,标志发生了借位 
}
result[resultindex--]=nminus+'0';
}
if(num1length<0)
{
while(num2length>=0)
{
if(num2[num2length]>=flag)
{
nminus=num2[num2length--]-'0'-flag;
flag=0;
}
else
{
nminus=num2[num2length--]-'0'-flag+10;
flag=1;
}
result[resultindex--]=nminus+'0';
}
}
if(num2length<0)
{
while(num1length>=0)
{
if(num1[num1length]>=flag)
{
nminus=num1[num1length--]-'0'-flag;
flag=0;
}
else
{
nminus=num1[num1length--]-'0'-flag+10;
flag=1;
}
result[resultindex--]=nminus+'0';
}
}
if(result[resultindex+1]!='0')
result[resultindex]='-';//注意这个负号的位置放置也是有讲究的,不能单纯的写为result[resultindex]='-',万一最高位刚好减为0,则要把负号放在高位上
else
result[resultindex+1]='-';
}

}

void print(char*num,int nlength)

{
bool isbegining=true;
if(Isequal)
cout<<'0'<<endl;
else
{
for(int i=0;i<nlength;i++)
{
if(num[i]!='\0')
{
if(isbegining&&num[i]!='0')//因为之前预留了空位,所以位数不够nlength位,之前为0,为了符合打印习惯,从左往右找到第一个非‘0’的值
isbegining=false;
if(!isbegining)
cout<<num[i];
}
}
cout<<endl;
}

}

int main()

{
char num1[]="123";
char num2[]="1000";
int num1length=strlen(num1)-1;//数组是从0开始
int num2length=strlen(num2)-1;//数组是从0开始
int maxlength=(num1length>num2length)? num1length:num2length;
int resultlength=maxlength+10;
int resultindex=resultlength;//用于Minus函数中数组result的标号,若不用它用resultlength则print的时候会出错
char* result=new char[resultlength];
memset(result,'0',resultlength-2);//减2是因为数组是从0开始,数组最后一位放置结束符。结果数组清0,调用了memset函数,注意是赋值‘0’而不是0,否则出错
result[resultlength-1]='\0';//数组添加结束符
resultindex--;//减掉一位,因为最后一位不放任何内容,只放结束符
Minus(num1,num2,result,num1length,num2length,resultindex);
print(result,resultlength);
return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: