C语言程序(大数公约数)

hzw1311 2013-01-08 08:47:09
本帖是有关于求大数的公约数,采用的是辗转相除法!大数存储在字符串当中!程序当中我分别重载了大数比较,大数相减,大数相除获得商与余数,可是调试中得不到正确结果 求助!真的很急,求各位大神帮帮忙
#include<stdio.h>
#include<string.h>
#define N 1001
int compare(char * c1,int s1,int e1,char *c2,int s2,int e2)/*大整数比较大小*/
{
while(c1[s1]=='0'&&s1<e1)s1++;
while(c2[s2]=='0'&&s2<e2)s2++;
if(e1-s1>e2-s2)return 0;
if(e1-s1<e2-s2)return 1;
int i1;int f11=0;
for(i1=0;i1<=e1-s1;i1++)
{
if(c1[s1+i1]>c2[s2+i1]){f11=1;break;}
if(c2[s2+i1]>c1[s1+i1])break;
}
if(i1>e1-s1||f11==1)return 0;
//if(f11)return 0;
return 1;
//return -1;
}
void sub(char *c1,int l1,char *c2,int n,int l)/*两个大整数相减,结果放在c1中*/
{
int fig=0;
if(l1>l)
{
fig=1;
int i5;
for(i5=l;i5>0;i5--)
c2[i5]=c2[i5-1];
c2[0]='0';l++;
}
int jw=0;
int i4;
char tc[N];
for(i4=l-1;i4>=0;i4--)
{
tc[i4]=((c2[i4]-48)*n+jw)%10+48;
jw=((c2[i4]-48)*n+jw)/10;
}
jw=0;
for(i4=l-1;i4>=0;i4--)
{
int ttt=jw;
if(c1[i4]-tc[i4]-jw>=0)
{
tc[i4]=c1[i4]-tc[i4]-jw+48;
jw=0;
}
else
{

jw=(tc[i4]-c1[i4]+jw);
if(jw%10==0)jw/=10;
else jw=jw/10+1;
tc[i4]=jw*10+c1[i4]-tc[i4]-ttt+48;
}
}
if(fig)
{
for(i4=0;i4<l-1;i4++)c2[i4]=c2[i4+1];
l--;
c2[l]='\0';
}
tc[l1]='\0';
for(i4=0;i4<=l1;i4++)
c1[i4]=tc[i4];
}
void high_precise_division(char *c1,char *c2)//求两个整数的余数
{
int len1,len2;

len1=strlen(c1);
len2=strlen(c2);
int i,j,k,ip;
i=0;
while(c1[i]=='0'&&i<len1-1)i++;
for(j=0;i<len1;j++,i++)c1[j]=c1[i];
len1=j;c1[j]='\0';
i=0;
while(c2[i]=='0'&&i<len2-1)i++;
for(j=0;i<len2;j++,i++)c2[j]=c2[i];
len2=j;c2[j]='\0';
/*while(c1[0]=='0'&&i<len1-1)
{
for(k=0;k<len1-1;k++)
c1[k]=c1[k+1];
len1--;
}去掉前面的0*/
/*while(c2[0]=='0'&&j<len2-1)
{
for(k=0;k<len2-1;k++)
c2[k]=c2[k+1];
len2--;
}去掉前面的0*/
c1[len1]='\0';
c2[len2]='\0';
if(strcmp(c2,"0")==0)return ;/*当除数为0时*/
if(strcmp(c1,"0")==0){strcpy(c2,"0");return ;}/*当被除数为0时*/
if(len1<len2||len1==len2&&compare(c1,0,len1-1,c2,0,len2-1)>0)
{
strcpy(c2,c1);
c1[0]='0';c1[1]='\0';
return ;
}
else
{
ip=0;
char product[N],*pr;/*部分积*/
pr=product;
for(ip=0;ip<len2-1;ip++)
pr[ip]=c1[ip];
for(i=0;i<=len1-len2;i++)
{
pr[ip++]=c1[len2-1+i];
if(ip>=len2&&compare(pr,0,ip-1,c2,0,len2-1)==0)
{
char tc[N];
for(j=1;j<=9;j++)
{
for(k=0;k<ip;k++)tc[k]=pr[k];
sub(tc,ip,c2,j,len2);/*pr-c2*j结果放在tc中*/
for(k=0;tc[k]!='\0';k++);
if(compare(tc,0,k-1,c2,0,len2-1)>0)
break;
}
strcpy(pr,tc);
ip=strlen(pr);
c1[i]=j+48;
while(pr[0]=='0'&&ip>1)
{
for(j=0;j<ip-1;j++)
pr[j]=pr[j+1];
ip--;
}
if(ip==1&&pr[0]=='0')ip--;
}
else c1[i]='0';
}
while(c1[0]=='0')
{
for(j=0;j<i-1;j++)
c1[j]=c1[j+1];
i--;
}
c1[i]='\0';
if(ip==0){pr[0]='0';pr[1]='\0';ip=1;}
else
{
while(pr[0]=='0'&&ip>1)
{
for(j=0;j<ip-1;j++)pr[j]=pr[j+1];
ip--;
}
}
for(j=0;j<ip;j++)
c2[j]=pr[j];
c2[ip]='\0';
return ;
}
}
int Judge(char *J)//判断字符串是否为0
{ int i;
for(i=0;i<strlen(J);i++)
{
if(J[i]!='0')
return 0;
}
return 1;
}
char* gcd(char* a,char* b)//辗转相除
{
char* m1=b;
int len1,len2;
len1=strlen(a);
len2=strlen(b);
//high_precise_division(a,b);
//char* m=b;
//int len1,len2;
// len1=strlen(a);
//len2=strlen(b);
char* c;
if (compare(a,0,len1-1,b,0,len2-1))
{
strcpy(c,a);//交换
strcpy(a,b);
strcpy(b,c);
}
high_precise_division(a,b);
char* m=b;
if (Judge(m))
{
//m=b;
return m1;
}
else
{
return gcd(m1,m);
}
}
int main()
{
int i,j;
char c1[N],c2[N];/*整数高精度除法*/
while(scanf("%s %s",c1,c2)!=EOF)
{
char *pc1,*pc2,*pc3;
pc1=c1;pc2=c2;
c1[strlen(c1)]='\0';
c2[strlen(c2)]='\0';
pc3=gcd(pc1,pc2);
//high_precise_division(pc1,pc2);/*结果放在pC1中,余数放在pC2中*/
//printf(" 商:%s\n",pc3);
puts(pc3);
}
return 0;
}
...全文
314 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
hzw1311 2013-01-14
  • 打赏
  • 举报
回复
引用 11 楼 gumh 的回复:
隨便掃了一眼,只看了下面的函數,其他的沒看,不少錯誤, 整個函數看不來"辗转相除"的過程. char* gcd(char* a,char* b)//辗转相除求公约数 { char* m1=b; int len1,len2; len1=strlen(a); len2=strlen(b); char* c; ……
谢谢提醒!很有帮助哦!
MoreWindows 2013-01-08
  • 打赏
  • 举报
回复
求公约数可以用另一种方法: 若x和y均为偶数, f(x,y) = 2*f(x/2, y/2) = 2* f(x>>1, y>>1) 若x为偶数,y为奇数, f(x,y) = f(x/2, y) = f(x>>1, y) 若x为奇数,y为偶数, f(x,y) = f(x, y>>1) 若x和y均为奇数,f(x,y) = f(y, x-y),这样x-y必定为偶数,下一步可以除以2进行缩小。
ForestDB 2013-01-08
  • 打赏
  • 举报
回复
先把大数的+-*/比较的函数写好。
樱木花道 2013-01-08
  • 打赏
  • 举报
回复
格式凌乱 ,代码太多, 无时间看完整。
prajna 2013-01-08
  • 打赏
  • 举报
回复
隨便掃了一眼,只看了下面的函數,其他的沒看,不少錯誤, 整個函數看不來"辗转相除"的過程. char* gcd(char* a,char* b)//辗转相除求公约数 { char* m1=b; int len1,len2; len1=strlen(a); len2=strlen(b); char* c; //c沒有分配内存 if (compare(a,0,len1-1,b,0,len2-1)) { strcpy(c,a);//交换 strcpy(a,b); strcpy(b,c); } char* m= high_precise_division(a,b); if (strcmp(m,0)) //是不是strcmp(m,"0") { return m1; } else { return gcd(m1,m); } }
hzw1311 2013-01-08
  • 打赏
  • 举报
回复
引用 2 楼 lile1234_show 的回复:
哪部不对,就在哪不加断点,F11,F10调试就行。
我自己调试过了 可还是一直调试不出来啊!谁能帮我看看程序啊!
lee_鹿游原 2013-01-08
  • 打赏
  • 举报
回复
哪部不对,就在哪不加断点,F11,F10调试就行。
jimette 2013-01-08
  • 打赏
  • 举报
回复
lz f10一步一步调吧!
赵4老师 2013-01-08
  • 打赏
  • 举报
回复
请在我8楼代码基础上改。
hzw1311 2013-01-08
  • 打赏
  • 举报
回复
我把代码整理了一下,这样看起来可能会比较直观点,真的希望哪位高手能够帮忙看下,我是一名新手,希望前辈们指导指导,一定加分!
#include<stdio.h>
#include<string.h>
#define N 1001
int compare(char * c1,int s1,int e1,char *c2,int s2,int e2)/*大整数比较大小*/
{
	while(c1[s1]=='0'&&s1<e1)s1++;
	while(c2[s2]=='0'&&s2<e2)s2++;
	if(e1-s1>e2-s2)return 0;
	if(e1-s1<e2-s2)return 1;
	int i1;int f11=0;
	for(i1=0;i1<=e1-s1;i1++)
	{
		if(c1[s1+i1]>c2[s2+i1]){f11=1;break;}
		if(c2[s2+i1]>c1[s1+i1])break;
	}
	if(i1>e1-s1||f11==1)return 0;
	return 1;
}
void sub(char *c1,int l1,char *c2,int n,int l)/*两个大整数相减,结果放在c1中*/
{
	int fig=0;
	if(l1>l)
	{
		fig=1;
		int i5;
		for(i5=l;i5>0;i5--)
			c2[i5]=c2[i5-1];
		c2[0]='0';l++;
	}
	int jw=0;
	int i4;
	char tc[N];
	for(i4=l-1;i4>=0;i4--)
	{
		tc[i4]=((c2[i4]-48)*n+jw)%10+48;
		jw=((c2[i4]-48)*n+jw)/10;
	}
	jw=0;
	for(i4=l-1;i4>=0;i4--)
	{
		int ttt=jw;
		if(c1[i4]-tc[i4]-jw>=0)
		{
			tc[i4]=c1[i4]-tc[i4]-jw+48;
			jw=0;
		}
		else
		{

			jw=(tc[i4]-c1[i4]+jw);
			if(jw%10==0)jw/=10;
			else jw=jw/10+1;
			tc[i4]=jw*10+c1[i4]-tc[i4]-ttt+48;
		}
	}
	if(fig)
	{
		for(i4=0;i4<l-1;i4++)c2[i4]=c2[i4+1];
		l--;
		c2[l]='\0';
	}
	tc[l1]='\0';
	for(i4=0;i4<=l1;i4++)
		c1[i4]=tc[i4];
}		
char* high_precise_division(char *c1,char *c2)//求两个整数的余数
{
	int len1,len2;
    char* t;
	char* t1=NULL;
	len1=strlen(c1);
	len2=strlen(c2);
	int i,j,k,ip;
	i=0;
	while(c1[i]=='0'&&i<len1-1)i++;
	for(j=0;i<len1;j++,i++)c1[j]=c1[i];
	len1=j;c1[j]='\0';
	i=0;
	while(c2[i]=='0'&&i<len2-1)i++;
	for(j=0;i<len2;j++,i++)c2[j]=c2[i];
	len2=j;c2[j]='\0';
	c1[len1]='\0';
	c2[len2]='\0';
	if(strcmp(c2,"0")==0)return t1 ;/*当除数为0时*/
	if(strcmp(c1,"0")==0){strcpy(c2,"0");t=c2;return t ;}/*当被除数为0时*/
	if(len1<len2||len1==len2&&compare(c1,0,len1-1,c2,0,len2-1)>0)
	{
		strcpy(c2,c1);
		c1[0]='0';c1[1]='\0';
		t=c2;
		return t;
	}
	else
	{
		ip=0;
		char product[N],*pr;/*部分积*/
		pr=product;
		for(ip=0;ip<len2-1;ip++)
			pr[ip]=c1[ip];
		for(i=0;i<=len1-len2;i++)
		{
			pr[ip++]=c1[len2-1+i];
			if(ip>=len2&&compare(pr,0,ip-1,c2,0,len2-1)==0)
			{
				char tc[N];
				for(j=1;j<=9;j++)
				{
					for(k=0;k<ip;k++)tc[k]=pr[k];	
					sub(tc,ip,c2,j,len2);/*pr-c2*j结果放在tc中*/
					for(k=0;tc[k]!='\0';k++);
					if(compare(tc,0,k-1,c2,0,len2-1)>0)
						break;
				}
				strcpy(pr,tc);
				ip=strlen(pr);
				c1[i]=j+48;
				while(pr[0]=='0'&&ip>1)
				{
					for(j=0;j<ip-1;j++)
						pr[j]=pr[j+1];
					ip--;
				}
				if(ip==1&&pr[0]=='0')ip--;
			}
			else c1[i]='0';
		}
		while(c1[0]=='0')
		{
			for(j=0;j<i-1;j++)
				c1[j]=c1[j+1];
			i--;
		}
		c1[i]='\0';
		if(ip==0){pr[0]='0';pr[1]='\0';ip=1;}
		else
		{
			while(pr[0]=='0'&&ip>1)
			{
				for(j=0;j<ip-1;j++)pr[j]=pr[j+1];
				ip--;
			}
		}
		for(j=0;j<ip;j++)
			c2[j]=pr[j];
		c2[ip]='\0';
		t=c2;
		return t;
	}
}
char* gcd(char* a,char* b)//辗转相除求公约数
        {
			char* m1=b;
            int len1,len2;
	        len1=strlen(a);
	        len2=strlen(b);
			char* c;
            if (compare(a,0,len1-1,b,0,len2-1))
            {
                strcpy(c,a);//交换
				strcpy(a,b);
				strcpy(b,c);
            }
          char* m= high_precise_division(a,b);
		   
            if (strcmp(m,0))
            {
				return m1;
            }
            else
            {
                return gcd(m1,m);
            }
        }
int main()
{
	int i,j;
	char c1[N],c2[N];/*整数高精度除法*/
	while(scanf("%s %s",c1,c2)!=EOF)
	{
		char *pc1,*pc2,*pc3;
		pc1=c1;pc2=c2;
		c1[strlen(c1)]='\0';
		c2[strlen(c2)]='\0';
		pc3=gcd(pc1,pc2);
	    puts(pc3);
		return 0;
	}
	//return 0;
}
赵4老师 2013-01-08
  • 打赏
  • 举报
回复
仅供参考
#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);
}
hzw1311 2013-01-08
  • 打赏
  • 举报
回复
引用 6 楼 MoreWindows 的回复:
求公约数可以用另一种方法: 若x和y均为偶数, f(x,y) = 2*f(x/2, y/2) = 2* f(x>>1, y>>1) 若x为偶数,y为奇数, f(x,y) = f(x/2, y) = f(x>>1, y) 若x为奇数,y为偶数, f(x,y) = f(x, y>>1) 若x和y均为奇数,f(x,y) = f(y, x-y),这样x-y必定为偶数,下一步可以除以2进行缩小。 ……
这种方法我也试过,用C#写的也是结果有问题!http://bbs.csdn.net/topics/390335424?page=1#post-393368744

69,373

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧