user-0 提问: 用c语言解决大整数减法问题

回复:
user: user-0
content: 没有考虑效率神马的，只是实习功能。。  # include<stdio.h> # include<string.h>  # include<stdio.h> # include<string.h> struct BigInt{ 	int num[1000];//存放大整数的每位数据 	int length;//记录大整数的长度 	void init() 	{ 		for(int i=0;i<1000;i++) 			num[i]=0; 		length=0; 	}//初始化 	void set(char str[])//用字符串输入数据，所以要提取出来 	{ 		init();//初始化 		int j=0; 		int size; 		size=strlen(str); 		for(j=size-1;j>=0;j--) 		{ 			num[length++]=str[j]-'0'; 		} 	} 	void output()//大整数的输出 	{ 		int add=0;//记录前面的零  		for(int k=length-1;k>=0;k--) 		{ 			add+=num[k];//采用折叠法去掉前面的零 			if(add) 			{ 				printf("%d",num[k]); 			} 		} 		printf("\n"); 	}  }a,b,c;  	BigInt sub(BigInt a,BigInt b)//这里假定a>b 	{ 			BigInt ans;//存放和 			memset(ans.num,0,sizeof(ans.num));//将内存空间设为0 			ans.length=0; 			int carry=0;//进位位 			  			for(int i=0;i<a.length||i<b.length;i++) 			{ 				if(a.num[i]+carry<b.num[i]) 				{ 					int temp=a.num[i]+10-b.num[i]+carry;//记得加进位位 					ans.num[ans.length++]=temp; 					carry=-1; 				} 				else if(a.num[i]+carry>=b.num[i]) 				{ 					int temp=a.num[i]-b.num[i]+carry; 					ans.num[ans.length++]=temp; 					carry=0; 				} 			} 	return ans;		 	} 	int main(void) { char str1[1000],str2[1000]; while(scanf("%s%s",str1,str2)!=EOF) { 	 	a.set(str1); 	b.set(str2); 	if(a.length>b.length)//如果a的长度大于b，直接减去 	{ 		c=sub(a,b); 		c.output(); 	} 	else if(a.length<b.length)//这个地方也很简单 	{ 		c=sub(b,a); 		printf("-");//这里大数减去小数 		c.output(); 	} 	else if(a.length==b.length) 	{ 	 for(int i=a.length-1;i>=0;i--) 	 { 		 if(a.num[i]!=b.num[i])//如果相等，则一直找到不等的地方跳出 		 { 			 break; 		 } 	 } 	 if(i>=a.length)//如果两个数组中的数据一样 	 { 		 printf("0\n"); 	 } 	 else 	 { 		 if(a.num[i]>b.num[i])//继续比较 		 { 			 	c=sub(a,b); 				c.output(); 		 } 		 else if(a.num[i]<b.num[i]) 		 { 			 		c=sub(b,a); 					printf("-"); 					c.output();  		 } 	 }  	} } return 0; }

user: user-0
content: 自己一个小时写出来了一个简单的，赵老师的太复杂，看不太明白

user: user-0
content: 引用 11 楼 zhao4zhong1 的回复:来个简单点的： #include <stdio.h> #include <string.h> #define MAXLEN 1000 char a1[MAXLEN]; char a2[MAXLEN]; static int v1[MAXLEN]; static int v2[MAXLEN]; static int v3[MAXLEN]; int i,j,n,L,z; void main(void) {     scanf("%d",&n);     for (j=0;j<n;j++) {         scanf("%s%s",a1,a2);          L=strlen(a1);         for (i=0;i<L;i++) v1[i]=a1[L-1-i]-'0';          L=strlen(a2);         for (i=0;i<L;i++) v2[i]=a2[L-1-i]-'0';          for (i=0;i<MAXLEN;i++) v3[i]=v1[i]+v2[i];          for (i=0;i<MAXLEN;i++) {             if (v3[i]>=10) {                 v3[i+1]+=v3[i]/10;                 v3[i]=v3[i]%10;             }         }          printf("Case %d:\n", j+1);         printf("%s + %s = ", a1, a2);          z=0;         for (i=MAXLEN-1;i>=0;i--) {             if (z==0) {                 if (v3[i]!=0) {                     printf("%d",v3[i]);                     z=1;                 }             } else {                 printf("%d",v3[i]);             }         }         if (z==0) printf("0");          printf("\n");     } } //Sample Input //3 //0 0 //1 2 //112233445566778899 998877665544332211 // //Sample Output //Case 1: //0 + 0 = 0 //Case 2: //1 + 2 = 3 //Case 3: //112233445566778899 + 998877665544332211 = 1111111111111111110  谢谢赵老师。。。。。。不常上网，今天才看到。

user: user-0
content: 引用 9 楼 u012421456 的回复:看来我水平还差得很远，唉，不说了，学习 我目前也在疯狂补习中。。。 复试要编程的。。。必须努力！！！

user: user-0
content: 引用 13 楼 landdy_lain 的回复:1.先判符号, 减负变成加法. 2.相同位相减, 考虑借位.  有点好奇的是, 佬场合用到大数, 科研所的? 不是，计算机考研复试的时候复习到的题目。

user: user-1
content: 那祝lz成功啊

user: user-2
content: 1.先判符号, 减负变成加法. 2.相同位相减, 考虑借位.  有点好奇的是, 佬场合用到大数, 科研所的?

user: user-3
content: char* BigNumMinus(char* v1, char* v2) { 	int maxSize = strlen(v1) > strlen(v2) ? strlen(v1) : strlen(v2); 	char* p = new char[maxSize + 1]; 	memset(p, 0, maxSize + 1); 	char* pv1 = v1 + strlen(v1) - 1; 	char* pv2 = v2 + strlen(v2) - 1;  	int t = 0; 	int m = 0;  	for (int i = maxSize; i > 0; --i) 	{ 		t = 0; 		m = 0; 		if ((pv1+1) != v1) 		{ 			t = *pv1 - 48; 			pv1--; 		} 		if ((pv2+1) != v2) 		{ 			m = *pv2 - 48; 			pv2--; 		} 		if (t < m) 		{ 			t += 10; 			*pv1 = ((*pv1 - 48) - 1) + 48; 			*(p + i - 1) = (t - m) + 48; 		} 		else if(t >= m) 		{ 			*(p + i - 1) = (t - m) + 48;   		} 	}  	return p; }  没考虑负数，LZ可以自己扩展一下。

user: user-4
content: 来个简单点的： #include <stdio.h> #include <string.h> #define MAXLEN 1000 char a1[MAXLEN]; char a2[MAXLEN]; static int v1[MAXLEN]; static int v2[MAXLEN]; static int v3[MAXLEN]; int i,j,n,L,z; void main(void) {     scanf("%d",&n);     for (j=0;j<n;j++) {         scanf("%s%s",a1,a2);          L=strlen(a1);         for (i=0;i<L;i++) v1[i]=a1[L-1-i]-'0';          L=strlen(a2);         for (i=0;i<L;i++) v2[i]=a2[L-1-i]-'0';          for (i=0;i<MAXLEN;i++) v3[i]=v1[i]+v2[i];          for (i=0;i<MAXLEN;i++) {             if (v3[i]>=10) {                 v3[i+1]+=v3[i]/10;                 v3[i]=v3[i]%10;             }         }          printf("Case %d:\n", j+1);         printf("%s + %s = ", a1, a2);          z=0;         for (i=MAXLEN-1;i>=0;i--) {             if (z==0) {                 if (v3[i]!=0) {                     printf("%d",v3[i]);                     z=1;                 }             } else {                 printf("%d",v3[i]);             }         }         if (z==0) printf("0");          printf("\n");     } } //Sample Input //3 //0 0 //1 2 //112233445566778899 998877665544332211 // //Sample Output //Case 1: //0 + 0 = 0 //Case 2: //1 + 2 = 3 //Case 3: //112233445566778899 + 998877665544332211 = 1111111111111111110

user: user-5
content: 推荐LZ去看下这本书，上面有你需要的算法（算法2.6） http://download.csdn.net/detail/kyzaqlx/4586221

user: user-1
content: 引用 楼主 u012494310 的回复:用数组存放整数，实现减法  唉，我也没想明白lz想怎么干什么，用数组存放整数，实现减法？能不能再具体描述一下？

user: user-1
content: 看来我水平还差得很远，唉，不说了，学习

user: user-6
content: 参考我的博文（http://blog.csdn.net/turingo/article/details/8249799） 你可以去研究GMP库的源代码。  引用 楼主 u012494310 的回复:用数组存放整数，实现减法，感觉很复杂，木有思路。。。哪位大神会？可否贴一下代码。。

user: user-0
content: 引用 5 楼 zhao4zhong1 的回复:#include <iostream> #include <string> using namespace std; inline int compare(string str1,string str2) {//相等返回0，大于返回1，小于返回-1          if (str1.size()>str2.size()) return 1; //长度长的整数大于长度小的整数     else if (str1.size()<str2.size()) return -1;     else                              return str1.compare(str2); //若长度相等，则头到尾按位比较 } string SUB_INT(string str1,string str2); string ADD_INT(string str1,string str2) {//高精度加法     int sign=1; //sign 为符号位     string str;     if (str1[0]=='-') {         if (str2[0]=='-') {             sign=-1;             str=ADD_INT(str1.erase(0,1),str2.erase(0,1));         } else {             str=SUB_INT(str2,str1.erase(0,1));         }     } else {         if (str2[0]=='-') {             str=SUB_INT(str1,str2.erase(0,1));         } else { //把两个整数对齐，短整数前面加0补齐             string::size_type L1,L2;             int i;             L1=str1.size();             L2=str2.size();             if (L1<L2) {                 for (i=1;i<=L2-L1;i++) str1="0"+str1;             } else {                 for (i=1;i<=L1-L2;i++) str2="0"+str2;             }             int int1=0,int2=0; //int2 记录进位             for (i=str1.size()-1;i>=0;i--) {                 int1=(int(str1[i])-'0'+int(str2[i])-'0'+int2)%10;                 int2=(int(str1[i])-'0'+int(str2[i])-'0'+int2)/10;                 str=char(int1+'0')+str;             }             if (int2!=0) str=char(int2+'0')+str;         }     }     //运算后处理符号位     if ((sign==-1)&&(str[0]!='0')) str="-"+str;     return str; } string SUB_INT(string str1,string str2) {//高精度减法     int sign=1; //sign 为符号位     string str;     int i,j;     if (str2[0]=='-') {         str=ADD_INT(str1,str2.erase(0,1));     } else {         int res=compare(str1,str2);         if (res==0) return "0";         if (res<0) {             sign=-1;             string temp =str1;             str1=str2;             str2=temp;         }         string::size_type tempint;         tempint=str1.size()-str2.size();         for (i=str2.size()-1;i>=0;i--) {             if (str1[i+tempint]<str2[i]) {                 j=1;                 while (1) {//zhao4zhong1添加                     if (str1[i+tempint-j]=='0') {                         str1[i+tempint-j]='9';                         j++;                     } else {                         str1[i+tempint-j]=char(int(str1[i+tempint-j])-1);                         break;                     }                 }                 str=char(str1[i+tempint]-str2[i]+':')+str;             } else {                 str=char(str1[i+tempint]-str2[i]+'0')+str;             }         }         for (i=tempint-1;i>=0;i--) str=str1[i]+str;     }     //去除结果中多余的前导0     str.erase(0,str.find_first_not_of('0'));     if (str.empty()) str="0";     if ((sign==-1) && (str[0]!='0')) str ="-"+str;     return str; } string MUL_INT(string str1,string str2) {//高精度乘法     int sign=1; //sign 为符号位     string str;     if (str1[0]=='-') {         sign*=-1;         str1 =str1.erase(0,1);     }     if (str2[0]=='-') {         sign*=-1;         str2 =str2.erase(0,1);     }     int i,j;     string::size_type L1,L2;     L1=str1.size();     L2=str2.size();     for (i=L2-1;i>=0;i--) { //模拟手工乘法竖式         string tempstr;         int int1=0,int2=0,int3=int(str2[i])-'0';         if (int3!=0) {             for (j=1;j<=(int)(L2-1-i);j++) tempstr="0"+tempstr;             for (j=L1-1;j>=0;j--) {                 int1=(int3*(int(str1[j])-'0')+int2)%10;                 int2=(int3*(int(str1[j])-'0')+int2)/10;                 tempstr=char(int1+'0')+tempstr;             }             if (int2!=0) tempstr=char(int2+'0')+tempstr;         }         str=ADD_INT(str,tempstr);     }     //去除结果中的前导0     str.erase(0,str.find_first_not_of('0'));     if (str.empty()) str="0";     if ((sign==-1) && (str[0]!='0')) str="-"+str;     return str; } string DIVIDE_INT(string str1,string str2,int flag) {//高精度除法。flag==1时,返回商; flag==0时,返回余数     string quotient,residue; //定义商和余数     int sign1=1,sign2=1;     if (str2 == "0") {  //判断除数是否为0         quotient= "ERROR!";         residue = "ERROR!";         if (flag==1) return quotient;         else         return residue ;     }     if (str1=="0") { //判断被除数是否为0         quotient="0";         residue ="0";     }     if (str1[0]=='-') {         str1   = str1.erase(0,1);         sign1 *= -1;         sign2  = -1;     }     if (str2[0]=='-') {         str2   = str2.erase(0,1);         sign1 *= -1;     }     int res=compare(str1,str2);     if (res<0) {         quotient="0";         residue =str1;     } else if (res == 0) {         quotient="1";         residue ="0";     } else {         string::size_type L1,L2;         L1=str1.size();         L2=str2.size();         string tempstr;         tempstr.append(str1,0,L2-1);         for (int i=L2-1;i<L1;i++) { //模拟手工除法竖式             tempstr=tempstr+str1[i];             tempstr.erase(0,tempstr.find_first_not_of('0'));//zhao4zhong1添加             if (tempstr.empty()) tempstr="0";//zhao4zhong1添加             for (char ch='9';ch>='0';ch--) { //试商                 string str;                 str=str+ch;                 if (compare(MUL_INT(str2,str),tempstr)<=0) {                     quotient=quotient+ch;                     tempstr =SUB_INT(tempstr,MUL_INT(str2,str));                     break;                 }             }         }         residue=tempstr;     }     //去除结果中的前导0     quotient.erase(0,quotient.find_first_not_of('0'));     if (quotient.empty()) quotient="0";     if ((sign1==-1)&&(quotient[0]!='0')) quotient="-"+quotient;     if ((sign2==-1)&&(residue [0]!='0')) residue ="-"+residue ;     if (flag==1) return quotient;     else         return residue ; } string DIV_INT(string str1,string str2) {//高精度除法,返回商     return DIVIDE_INT(str1,str2,1); } string MOD_INT(string str1,string str2) {//高精度除法,返回余数     return DIVIDE_INT(str1,str2,0); } int main() {     char ch;     string s1,s2,res;      while (cin>>s1>>ch>>s2) {         switch (ch) {             case '+':res=ADD_INT(s1,s2);break;             case '-':res=SUB_INT(s1,s2);break;             case '*':res=MUL_INT(s1,s2);break;             case '/':res=DIV_INT(s1,s2);break;             case '%':res=MOD_INT(s1,s2);break;             default :                   break;         }         cout<<res<<endl;     }     return(0); }   好长。。一会运动回来，慢慢研究。。

user: user-0
content: 引用 2 楼 u013967255 的回复:我连题目都没看明白，郁闷中那你看下我贴的代码

user: user-0
content: 引用 3 楼 u012421456 的回复:[quote=引用 楼主 u012494310 的回复:] 用数组存放整数，实现减法  唉，我也没想明白lz想怎么干什么，用数组存放整数，实现减法？能不能再具体描述一下？[/quote]  这是我写的加法。。感觉减法很复杂呀！ # include<stdio.h> # include<string.h> struct BigInt{ 	int num[1000];//存放大整数的每位数据 	int length;//记录大整数的长度 	void init() 	{ 		for(int i=0;i<1000;i++) 			num[i]=0; 		length=0; 	} 	void set(char str[]) 	{ 		init();//初始化 		int j=0; 		int size; 		size=strlen(str); 		for(j=size-1;j>=0;j--) 		{ 			num[length++]=str[j]-'0'; 		} 	} 	void output() 	{ 		for(int k=length-1;k>=0;k--) 			printf("%d",num[k]); 		printf("\n"); 	}  }a,b,c; 	BigInt add(BigInt a,BigInt b) { 	BigInt ans;//存放和 	memset(ans.num,0,sizeof(ans.num));//将内存空间设为0 	ans.length=0; 	int carry=0;//进位位 	for(int i=0;i<a.length||i<b.length;i++) 	{ 		int temp; 		temp=a.num[i]+b.num[i]+carry; 		ans.num[ans.length++]=temp%10; 		carry=temp/10; 	} 	if(carry!=0){ 		ans.num[ans.length++]=carry; 	} 	return ans; }  int main(void) { char str1[1000],str2[1000]; while(scanf("%s%s",str1,str2)!=EOF) { 	a.set(str1); 	b.set(str2);     c=add(a,b); 	c.output(); } return 0; }

user: user-4
content: #include <iostream> #include <string> using namespace std; inline int compare(string str1,string str2) {//相等返回0，大于返回1，小于返回-1          if (str1.size()>str2.size()) return 1; //长度长的整数大于长度小的整数     else if (str1.size()<str2.size()) return -1;     else                              return str1.compare(str2); //若长度相等，则头到尾按位比较 } string SUB_INT(string str1,string str2); string ADD_INT(string str1,string str2) {//高精度加法     int sign=1; //sign 为符号位     string str;     if (str1[0]=='-') {         if (str2[0]=='-') {             sign=-1;             str=ADD_INT(str1.erase(0,1),str2.erase(0,1));         } else {             str=SUB_INT(str2,str1.erase(0,1));         }     } else {         if (str2[0]=='-') {             str=SUB_INT(str1,str2.erase(0,1));         } else { //把两个整数对齐，短整数前面加0补齐             string::size_type L1,L2;             int i;             L1=str1.size();             L2=str2.size();             if (L1<L2) {                 for (i=1;i<=L2-L1;i++) str1="0"+str1;             } else {                 for (i=1;i<=L1-L2;i++) str2="0"+str2;             }             int int1=0,int2=0; //int2 记录进位             for (i=str1.size()-1;i>=0;i--) {                 int1=(int(str1[i])-'0'+int(str2[i])-'0'+int2)%10;                 int2=(int(str1[i])-'0'+int(str2[i])-'0'+int2)/10;                 str=char(int1+'0')+str;             }             if (int2!=0) str=char(int2+'0')+str;         }     }     //运算后处理符号位     if ((sign==-1)&&(str[0]!='0')) str="-"+str;     return str; } string SUB_INT(string str1,string str2) {//高精度减法     int sign=1; //sign 为符号位     string str;     int i,j;     if (str2[0]=='-') {         str=ADD_INT(str1,str2.erase(0,1));     } else {         int res=compare(str1,str2);         if (res==0) return "0";         if (res<0) {             sign=-1;             string temp =str1;             str1=str2;             str2=temp;         }         string::size_type tempint;         tempint=str1.size()-str2.size();         for (i=str2.size()-1;i>=0;i--) {             if (str1[i+tempint]<str2[i]) {                 j=1;                 while (1) {//zhao4zhong1添加                     if (str1[i+tempint-j]=='0') {                         str1[i+tempint-j]='9';                         j++;                     } else {                         str1[i+tempint-j]=char(int(str1[i+tempint-j])-1);                         break;                     }                 }                 str=char(str1[i+tempint]-str2[i]+':')+str;             } else {                 str=char(str1[i+tempint]-str2[i]+'0')+str;             }         }         for (i=tempint-1;i>=0;i--) str=str1[i]+str;     }     //去除结果中多余的前导0     str.erase(0,str.find_first_not_of('0'));     if (str.empty()) str="0";     if ((sign==-1) && (str[0]!='0')) str ="-"+str;     return str; } string MUL_INT(string str1,string str2) {//高精度乘法     int sign=1; //sign 为符号位     string str;     if (str1[0]=='-') {         sign*=-1;         str1 =str1.erase(0,1);     }     if (str2[0]=='-') {         sign*=-1;         str2 =str2.erase(0,1);     }     int i,j;     string::size_type L1,L2;     L1=str1.size();     L2=str2.size();     for (i=L2-1;i>=0;i--) { //模拟手工乘法竖式         string tempstr;         int int1=0,int2=0,int3=int(str2[i])-'0';         if (int3!=0) {             for (j=1;j<=(int)(L2-1-i);j++) tempstr="0"+tempstr;             for (j=L1-1;j>=0;j--) {                 int1=(int3*(int(str1[j])-'0')+int2)%10;                 int2=(int3*(int(str1[j])-'0')+int2)/10;                 tempstr=char(int1+'0')+tempstr;             }             if (int2!=0) tempstr=char(int2+'0')+tempstr;         }         str=ADD_INT(str,tempstr);     }     //去除结果中的前导0     str.erase(0,str.find_first_not_of('0'));     if (str.empty()) str="0";     if ((sign==-1) && (str[0]!='0')) str="-"+str;     return str; } string DIVIDE_INT(string str1,string str2,int flag) {//高精度除法。flag==1时,返回商; flag==0时,返回余数     string quotient,residue; //定义商和余数     int sign1=1,sign2=1;     if (str2 == "0") {  //判断除数是否为0         quotient= "ERROR!";         residue = "ERROR!";         if (flag==1) return quotient;         else         return residue ;     }     if (str1=="0") { //判断被除数是否为0         quotient="0";         residue ="0";     }     if (str1[0]=='-') {         str1   = str1.erase(0,1);         sign1 *= -1;         sign2  = -1;     }     if (str2[0]=='-') {         str2   = str2.erase(0,1);         sign1 *= -1;     }     int res=compare(str1,str2);     if (res<0) {         quotient="0";         residue =str1;     } else if (res == 0) {         quotient="1";         residue ="0";     } else {         string::size_type L1,L2;         L1=str1.size();         L2=str2.size();         string tempstr;         tempstr.append(str1,0,L2-1);         for (int i=L2-1;i<L1;i++) { //模拟手工除法竖式             tempstr=tempstr+str1[i];             tempstr.erase(0,tempstr.find_first_not_of('0'));//zhao4zhong1添加             if (tempstr.empty()) tempstr="0";//zhao4zhong1添加             for (char ch='9';ch>='0';ch--) { //试商                 string str;                 str=str+ch;                 if (compare(MUL_INT(str2,str),tempstr)<=0) {                     quotient=quotient+ch;                     tempstr =SUB_INT(tempstr,MUL_INT(str2,str));                     break;                 }             }         }         residue=tempstr;     }     //去除结果中的前导0     quotient.erase(0,quotient.find_first_not_of('0'));     if (quotient.empty()) quotient="0";     if ((sign1==-1)&&(quotient[0]!='0')) quotient="-"+quotient;     if ((sign2==-1)&&(residue [0]!='0')) residue ="-"+residue ;     if (flag==1) return quotient;     else         return residue ; } string DIV_INT(string str1,string str2) {//高精度除法,返回商     return DIVIDE_INT(str1,str2,1); } string MOD_INT(string str1,string str2) {//高精度除法,返回余数     return DIVIDE_INT(str1,str2,0); } int main() {     char ch;     string s1,s2,res;      while (cin>>s1>>ch>>s2) {         switch (ch) {             case '+':res=ADD_INT(s1,s2);break;             case '-':res=SUB_INT(s1,s2);break;             case '*':res=MUL_INT(s1,s2);break;             case '/':res=DIV_INT(s1,s2);break;             case '%':res=MOD_INT(s1,s2);break;             default :                   break;         }         cout<<res<<endl;     }     return(0); }

user: user-7
content: 我连题目都没看明白，郁闷中

user: user-8
content: 召唤赵老师中.....