回 帖 发 新 帖 刷新版面

主题:两极大数运算,源程序示例

/*程序使用范例:
cal n1 op n2
cal 123123123 + 8762548
cal 123123123 - 8762548
cal 123123123 * 8762548
cal 123123123 / 8762548
cal 123123123 /200 8762548  ##精确到200位
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

int cchkdig(char *r)
{ int i=0;  
  while(r[i]!='\0')
  { if(isdigit(r[i++])==0) return (0); }
  return (1);  
}

//去掉整数串表示前面多余的零,最后结果为空串时置为"0"
void cdel0(char *r)
{ unsigned int lr;  
  int i=0, j;  
  lr=strlen(r);  
  while(r[i]=='0') ++i;  
  if(i>0)
  { for(j=0; j<lr-i; ++j) r[j]=r[j+i];
for(j=lr-i; j<lr; ++j) r[j]='\0';
}
if(r[0]=='\0') r[0]='0';
}

//比较两个串表示整数的大小
int scmp(char *r, char *u)
{ unsigned int lr, lu;
char hc, *p;
cdel0(r);
cdel0(u);
lr=strlen(r);
lu=strlen(u);
if(lr>lu) return 1;  
  return (strcmp(r, u));  
}//end scmp()

//两个串表示数的减法
char *ssub(char *r, char *u)
{ unsigned int lr, lu, lp;  
  char hc, *p;  
  if(scmp(r, u)<0) return (NULL);
lr=strlen(r);
lu=strlen(u);
p=(char *)malloc((unsigned int)(lr+1)*sizeof(char));
for(i=0; i<lu; ++i)
{ h=r[lr-i-1]-u[lu-i-1]-c;
if(h<0) { c=1; h=h+10; }
else c=0;
p[i]=h+'0';
}
for (i=lu; i<lr; ++i)
{ h=r[lr-i-1]-'0'-c;
if(h<0) { c=1; h=h+10; }
else c=0;
p[i]='0'+h;
}
lp=i-1;
for(i=lp+1; i<lr+1; ++i) p[i]='\0';
for(i=0; i<(lp+1)/2; ++i)
{ hc=p[i]; p[i]=p[lp-1]; p[lp-i]=hc; }
return (p);
}//end ssub()

//两个串表示数的加法
char *sadd(char *r, char *u)
{ unsigned int lr, lu, lp;
int i, h, c=0;
char hc, *p;
lr=strlen(r);
lu=strlen(u);
if(lu>lr) { p=r; r=u; u=p; h=lr; lr=lu; lu=h; }

  p=(char *)malloc((unsigned int)(lr+2)*sizeof(char));  
  for(i=0; i<lu; ++i)
{ h=r[lr-i-1]-'0'+u[lu-i-1]-'0'+c;
if(h>9) { c=1; h=h-10; }
    else c=0;  
    p[i]=h+'0';  
  }
  for(i=lu; i<lr; ++i)
{ h=r[lr-i-1]-'0'+c;
if(h>9) { c=1; h=h-10; }
    else c=0;  
    p[i]='0'+h;  
  }
  if(c>0) { p[i]=c+'0'; lp=i; }
  else lp=i-1;  
  for(i=lp+1; i<lr+2; ++i) p[i]='\0';
for(i=0; i<(lp+1)/2; ++i)
{ hc=p[i]; p[i]=p[lp-i]; p[lp-i]=hc; }
return (p);
}//end sadd()

//两个串表示数的乘法
int *smut(char *r, char *u)
{ unsigned int lr, lu, lp;
int i, j, c, h;
char *p;
lr=strlen(r);
lu=strlen(u);
p=(char *)malloc((unsigned int)(lr+lu+1)*sizeof(char));
for(i=0; i<lr+lu; ++i) p[i]='\0';
p[lr+lu]='\0';

for(i=lr-1; i>=0; --i)
  { c=0;  
    for(j=lu-1; j>=0; --j)
    { lp=i+j+1;  
      h=(r[i]-'0')*(u[j]-'0')+p[lp]-'0'+c;  
      c=h/10;  
      h=h%10;  
      p[lp]=h+'0';  
    }
    if(c>0)p[i+j+1]=c+'0';  
  }
  cdel0(p);  
  return p;  
}//end smut()

//两个串表示数的除法,结果精确到小数点后第n位
char *sdivf(char *u, char *v, int n)
{ char *p, *f, *r;  
  unsigned int i, lu, lv, lr, iu, iw, c, h;  
  int mh, kh, j;  
  lu=strlen(u);  
  lv=strlen(v);  

  f=(char *)malloc((unsigned int)(lu+n+3)*sizeof(char));
  for(i=0; i<lu+n+3; ++i) f[i]='\0';

r=(char *)malloc((unsigned int)(lv+2)*sizeof(char));
for(i=0; i<lv+2; ++i) r[i]='\0';

for(iw=0; iw<lu+n+2; ++iw)
{ if(iw<lu)
{ cdel0(r); lr=strlen(r);
r[lr]=u[iw]; r[lr+1]='\0';
}
else if(iw>lu)
    { cdel0(r); if(scmp(r, "0")==0) break;  
      lr=strlen(r; r[lr]='0'; r[lr+1]='\0';  
    }
    else { f[lu]='.'; continue; }
    kh=0;  
    while(scmp(r, v)>=0)
    { r=ssub(p=r, v); free(p); ++kh; }
    f[iw]=kh+'0';  
  }
  if(iw==lu+n+2)
  { if(f[lu+n+1]>='5')
    { f[lu+n+1]='\0';  
      c=1;  
      for(j=lu+n; j>=0; --j)
      { if(c==0) break;  
        if(f[j]=='.') continue;  
        h=f[j]-'0'+c;  
        if(h>9) { h=h-10; c=1; }
        else c=\0;  
        f[j]=h+'0';  
      }
    }
    else f[lu+n+1]='\0';  
  }
  free(r);  
  cdel0(f);  
  return(f);  
}//end sdivf()

//两个串表示数的除法,结果分别用整商与余数表示
char *sdivkr(char *u, char *v, char **rout)
{ char *p, *f, *r;  
  unsigned int i, lu, lv, lr, iu, iw, c, h;  
  int mh, kh, j;  
  lu=strlen(u);  
  lv=strlen(v);  

  f=(char *)malloc((unsigned int)(lu+1)*sizeof(char));
  for(i=0; i<lu+1; ++i) f[i]='\0';
r=(char *)malloc((unsigned int)(lv+2)*sizeof(char));
for(i=0; i<lv+2; ++i) r[i]='\0';

for(iw=0; iw<lu; ++iw)
{ cdel0(r);
lr=strlen(r);
r[lr]=u[iw];
r[lr+1]='\0';
kh=0;
while(scmp(r, v)>=0)
    { r=ssub(p=r, v); free(p); ++kh; }
    f[iw]=kh+'0';  
  }
  cdel0(r);  
  *rout=r;  
  cdel0(f);  
  return(f);  
}//end *sdivkr()

//调用上述函数实现两任意长正整数任意指定精度的算术计算器程序
void main(int argc, char *argv[])
{ char *p, *r;  
  int n;  
  if(argc!=4) { printf("\n>>order n1 op n2"); exit(0); }
  cdel0(argv[1]);  
  if(cchkdig(argv[1]==0)
  { printf("Input data error, Input again!"); exit(0); }
  cdel0(argv[3]);  
  if(cchkdig(argv[3])==0)
  { printf("Input data error, Input again!"); exit(0); }

  if(strcmp0(argv[2], "+")==0)
  { printf("%s", p=sadd(argv[1], argv[3])); free(p); }

  else if(strcmp0(argv[2], "-")==0)
  { printf("%s", p=sadd(argv[1], argv[3])); free(p); }

  else if(strcmp0(argv[2], "*")==0)
  { printf("%s", p=smut(argv[1], argv[3])); free(p); }

  else if(argv[2][0]=='/' && strlen(argv[2])==1)
  { p=sdivkr(argv[1], argv[3], &r);  
    printf("k=%s r=%s", p, r);  
    free(p); free(r);  
  }

  else if(argv[2][0]=='/'&&strlen(argv[2])>1)
  { argv[2][0]='\0';  
    cdel0(argv[2]);  
    if(cchkdig(argv[2])==0)
    { printf("Input data error, Input again!"); exit (0); }
    n=atoi(argv[2]);  
    printf("%s", p=sdivf(argv[1], argv[3], n)); free(p);  
  }
}

回复列表 (共12个回复)

沙发

厉害呀!

板凳

编译不了。

3 楼

厉害!可以做开方,指数,对数运算吗?

4 楼

不错的,不过太骄傲了。要知道高手如云 ,前路无止境。
这是你的网站么?是的话,加我。

5 楼

楼顶的老兄!的确不错,不过有一些小错误,我改了一些,方便大家嘛!vc++6.0扁以通过。:)

/*程序使用范例:
cal n1 op n2
cal 123123123 + 8762548
cal 123123123 - 8762548
cal 123123123 * 8762548
cal 123123123 / 8762548
cal 123123123 /200 8762548  ##精确到200位
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

int cchkdig(char *r)
{
int i=0;  
while(r[i]!='\0')
{
if(isdigit(r[i++])==0)
return (0);
}
  return (1);  
}

//去掉整数串表示前面多余的零,最后结果为空串时置为"0"
void cdel0(char *r)
{
unsigned int lr;  
int i=0, j;
lr=strlen(r);  
while(r[i]=='0')
  ++i;
if(i>0)
{
for(j=0; j<lr-i; ++j)
r[j]=r[j+i];
for(j=lr-i; j<lr; ++j)
{
r[j]='\0';
}

}

if(r[0]=='\0')
{
r[0]='0';
}
}

int scmp(char *r, char *u)
{
unsigned int lr, lu;
cdel0(r);
cdel0(u);

lr=strlen(r);
lu=strlen(u);

if(lr>lu)
{
return 1;
}
else if (lr<lu)
{
return -1;
}
return (strcmp(r, u));

}//end scmp()

//两个串表示数的减法
char *ssub(char *r, char *u)
{
unsigned int i,lr, lu, lp,c=0;  
char h,hc;
char *p;
if(scmp(r, u)<0)
return NULL;
lr=strlen(r);
lu=strlen(u);
p=(char *)malloc((unsigned int)(lr+1)*sizeof(char));
for(i=0; i<lu; ++i)
{
h=r[lr-i-1]-u[lu-i-1]-c;
if(h<0)
{
c=1;
h=h+10;
}
else
c=0;
p[i]=h+'0';
hc=h+'0';
}
for (i=lu; i<lr; ++i)
{
h=r[lr-i-1]-'0'-c;
if(h<0)
{
c=1;
h=h+10;
}
else
c=0;
p[i]='0'+h;
hc='0'+h;
}
p[i]='\0';
lp=i-1;

while(p[lp]=='0'&&lp!=0)
{
p[lp]='\0';
lp--;
}


for(i=0; i<(lp+1)/2; ++i)
{
hc=p[i];
p[i]=p[lp-i];
p[lp-i]=hc;
}
return (p);
}//end ssub()

//两个串表示数的加法
char *sadd(char *r, char *u)
{
unsigned int lr, lu, lp;
int i, h, c=0;
char hc, *p;
lr=strlen(r);
lu=strlen(u);
if(lu>lr)
{
p=r;
r=u;
u=p;
h=lr;
lr=lu;
lu=h;
}
p=(char *)malloc((unsigned int)(lr+2)*sizeof(char));  
for(i=0; i<lu; ++i)
{
h=r[lr-i-1]-'0'+u[lu-i-1]-'0'+c;
if(h>9)
{
c=1;
h=h-10;
}
else
c=0;  
p[i]=h+'0';  
}
for(i=lu; i<lr; ++i)
{
h=r[lr-i-1]-'0'+c;
if(h>9)
{
c=1;
h=h-10;
}
else
c=0;  
p[i]='0'+h;  
}
if(c>0)
{
p[i]=c+'0';
lp=i;
}
else
lp=i-1;  
for(i=lp+1; i<lr+2; ++i)
p[i]='\0';
for(i=0; i<(lp+1)/2; ++i)
{
hc=p[i];
p[i]=p[lp-i];
p[lp-i]=hc;
}
return (p);
}//end sadd()

//两个串表示数的乘法
char *smut(char *r, char *u)
{
unsigned int lr, lu, lp;
int i, j, c, h;
char *p;
lr=strlen(r);
lu=strlen(u);
p=(char *)malloc((unsigned int)(lr+lu+1)*sizeof(char));
for(i=0; i<lr+lu; ++i)
p[i]='0';
p[lr+lu]='\0';

for(i=lr-1; i>=0; --i)
{
c=0;  
for(j=lu-1; j>=0; --j)
{
lp=i+j+1;  
h=(r[i]-'0')*(u[j]-'0')+p[lp]-'0'+c;  
c=h/10;  
 h=h%10;  
p[lp]=h+'0';  
}
if(c>0)p[i+j+1]=c+'0';  
}

cdel0(p);  
return p;  
}//end smut()

//两个串表示数的除法,结果精确到小数点后第n位
char *sdivf(char *u, char *v, int n)
{
char *p, *f, *r,*q;  
unsigned int i, lu, lv, lr,  iw, c, h;  
int  kh, j;  
lu=strlen(u);  
lv=strlen(v);  
f=(char *)malloc((unsigned int)(lu+n+3)*sizeof(char));
q=(char *)malloc(sizeof(char));
for(i=0; i<lu+n+3; ++i)
f[i]='\0';
r=(char *)malloc((unsigned int)(lv+2)*sizeof(char));
for(i=0; i<lv+2; ++i)
r[i]='\0';
for(iw=0; iw<lu+n+2; ++iw)
{
if(iw<lu)
{
cdel0(r);
lr=strlen(r);
r[lr]=u[iw];
r[lr+1]='\0';
}

else if(iw>lu)
{
cdel0(r);
q[0]='0';
if(scmp(r, q)==0)
{
break;
}
lr=strlen(r);
r[lr]='0';
r[lr+1]='\0';
}

else
{
f[lu]='.';
continue; 
}

kh=0;
while(scmp(r, v)>=0)
{
p=r;
r=ssub(p, v);
++kh;
}
f[iw]=kh+'0';
}
if(iw==lu+n+2)
{
if(f[lu+n+1]>='5')
{
f[lu+n+1]='\0';  
c=1;  
for(j=lu+n; j>=0; --j)
{
if(c==0)
{
break;  
}
if(f[j]=='.')
{
continue;
}
h=f[j]-'0'+c;  
if(h>9)
{
h=h-10;
c=1;
}
else
c='\0';  
f[j]=h+'0';
}
}
else
f[lu+n+1]='\0';

}
free(r);
free(p);
q=NULL;
free(q);
cdel0(f);  
return(f);  
}//end sdivf()

//两个串表示数的除法,结果分别用整商与余数表示
char *sdivkr(char *u, char *v, char **rout)
{
char  *f, *r;  
unsigned int i, lu, lv, lr, iw;  
int  kh;  
lu=strlen(u);  
lv=strlen(v);  

f=(char *)malloc((unsigned int)(lu+1)*sizeof(char));
for(i=0; i<lu+1; ++i) f[i]='\0';
r=(char *)malloc((unsigned int)(lv+2)*sizeof(char));
for(i=0; i<lv+2; ++i) r[i]='\0';

for(iw=0; iw<lu; ++iw)
{
cdel0(r);
lr=strlen(r);
r[lr]=u[iw];
r[lr+1]='\0';
kh=0;
while(scmp(r, v)>=0)
{
r=ssub(r, v);
++kh;
}
f[iw]=kh+'0';
}
cdel0(r);  
*rout=r;  
cdel0(f);
    return(f);

}//end *sdivkr()

//调用上述函数实现两任意长正整数任意指定精度的算术计算器程序
void main(int argc, char *argv[])
{
char *p, *r;  
int n;  
if(argc!=4)
{
if(argc!=3)
printf("\n>>\"order n1 op n2\" or n ! ");
exit(0);
}
cdel0(argv[1]);  
if(cchkdig(argv[1])==0)
{
printf("Input data error, Input again!");
exit(0);
}
cdel0(argv[3]);  
if(cchkdig(argv[3])==0)
{
printf("Input data error, Input again!");
exit(0);
}

if(strcmp(argv[2], "+")==0)
{
printf("%s", p=sadd(argv[1], argv[3]));
free(p);
}

else if(strcmp(argv[2], "-")==0)
{
printf("%s", p=ssub(argv[1], argv[3]));
free(p);
}

else if(strcmp(argv[2], "*")==0)
{
printf("%s", p=smut(argv[1], argv[3]));
free(p);
}

else if(argv[2][0]=='/' && strlen(argv[2])==1)
{
if(argv[3][0]=='0')
{
printf("error!devided by zero!!\n");
exit(0);
}
p=sdivkr(argv[1], argv[3], &r);  
printf("k=%s r=%s", p, r);  
free(p);
free(r);  
}

else if(argv[2][0]=='/'&&strlen(argv[2])>1)
{
if(argv[3][0]=='0')
{
printf("error!devided by zero!!\n");
exit(0);
}

argv[2][0]='\0';  
cdel0(argv[2]);  
if(cchkdig(argv[2])==0)
{
printf("Input data error, Input again!");
exit (0);
}
n=atoi(argv[2]);  
printf("%s", p=sdivf(argv[1], argv[3], n));
free(p);  
}


}

6 楼

除法的效率有点低了,怎么不用试商?

7 楼

怎么验证你算法的正确性呢?呵呵

8 楼

怎么不能运行亚

9 楼

楼主什么编译器亚,我VC6,错误好多!

5楼的没结果亚

10 楼

/*用数组存储数字,可以超越数据类型的限制,实现极大数的加法,减法和乘法 */
/*2005-3-7   梁见斌*/

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX 80

int a[MAX]={0}, b[MAX]={0};
int *r, *s;
char e[40], f[40];/* e[30]和f[30]存放以字符串形式输入的乘数和被乘数*/
char *p, *q;
   
void NiZhi(int *ShuZu, int len);/*把数字逆置,把个位数字存储在a[0]*/
void ZhuanHuan(char *ZhiFu, int *ShuZi, int len);/*把字符改存为整型数字*/
int PanDuan(int len);/*当len1=len2时判断a[]和 b[]谁大 */
void JiaFa(int len1, int len2);
void JianFa(int len1, int len2);
void ChengFa(int len1, int len2);

int main(void)
{
   int len1, len2;
   int choice;
   
   do{
       puts("请您选择操作的方式:");
        puts("\t加法请按1 ");
        puts("\t减法请按2 ");
        puts("\t乘法请按3 ");
        scanf("%d", &choice);
   }while(choice < 1 || choice >3);  
   
   r=a;
   s=b;
   p=e;
   q=f;
   puts("Inter m:");
   scanf("%s", p);
   puts("Inter n:");
   scanf("%s", q);
   
   len1=strlen(e);
   len2=strlen(f);
   ZhuanHuan(p, r, len1);
   ZhuanHuan(q, s, len2);
   
   NiZhi(r, len1);
   NiZhi(s, len2);

      switch(choice)
      {
         case 1: JiaFa(len1, len2);
                 break;
       case 2: JianFa(len1, len2);
                 break;          
      case 3: ChengFa(len1, len2);
                 break;
       default: printf("It's error");          
      }   
       
   system("pause");
   return 0;       
}   

void NiZhi(int *ShuZu, int len)
{
   int i, t;
   for(i=0; i<len/2; i++)
   {
      t=*(ShuZu+i);
      *(ShuZu+i)=*(ShuZu+len-i-1);
      *(ShuZu+len-i-1)=t;
   }
}

void ZhuanHuan(char *ZhiFu, int *ShuZi, int len)
{
   int i;
   for(i=0; i<=len-1; i++)
       *(ShuZi+i)=int(*(ZhiFu+i))-48;     
}

void ChengFa(int len1, int len2)
{
   int i, j, k;
   int c[MAX]={0}, aa[MAX]={0};/*a[max]和aa[max]存放被乘数,b[max]存放乘数,c[max]存放积*/
   int x, jinwei, d;
   
   for(i=0; i<=len2; i++)
   {
      for(j=0; j<=len1; j++)/*每次都使 aa[ ]表示被乘数*/
          aa[j]=a[j];
      d=20;/*提供足够多的存储空间以存放积的进位,此处设为20,可根据数据的大小调节*/
      jinwei=0;/*c表示积的进位,初值为0*/
     
      for(j=0; j<=len1+d; j++)/*用乘数的每一位从个位开始依次和被乘数相乘,用aa[ ]存储当前积*/
      {
         x=aa[j]*b[i]+jinwei;
         jinwei=x/10;
         aa[j]=x%10;
      }  
      while(a[j] == 0)/*用j表示现有数字的个数,多出的存储空间应消除*/
          j--;
          
      d=4;/*提供足够多的存储空间以存放积的进位,此处设为4,可根据数据的大小调节*/
      jinwei=0;/*c表示积的进位,初值为0*/
      for(k=0; k<=j+d; k++)/*c[max]存放原始积,注意每次把当前积与原始积时相加时两者的位置对应情况*/
      {
         x=aa[k]+c[k+i]+jinwei;
         jinwei=x/10;
         c[k+i]=x%10;
      }   
   }  
   k=k+i; /*用k表示现有数字的个数,多出的存储空间应消除*/
   while(c[k] == 0)
          k--;
          
   printf("%s *  %s =\n", p, q);
      for(i=k; i>=0; i--)
       printf("%d",c[i]);   
}

void JiaFa(int len1, int len2)
{
   int i, j;
   int x, jinwei, max;
   
   max=(len1 >= len2)?len1:len2;    
   jinwei=0;
   for(i=0; i<=max+2; i++)
   {
      x=a[i]+b[i]+jinwei;
      jinwei=x/10;
      a[i]=x%10;
   }  
   while(a[i] == 0)/*用j表示现有数字的个数,多出的存储空间应消除*/
       i--;
   printf("%s +  %s =\n", p, q);
      for(j=i; j>=0; j--)
       printf("%d",a[j]);
}   

void JianFa(int len1, int len2)
{
   int i, j;
   int max;
   int flag=0;
        
   if(len1 == len2)/*当len1=len2时判断a[]和 b[]谁大 */
       flag=PanDuan(len1);
   if((len1 > len2) || (len1 == len2) && flag)/*若m大于n直接按m-n计算*/
   {
      for(i=0; i<len1; i++)
      {
         if(a[i] >= b[i])
             a[i]=a[i]-b[i];
         else
         {
            a[i+1]-=1;
            a[i]=a[i]+10-b[i];
         }   
      }  
      while(a[i] == 0)/*用j表示现有数字的个数,多出的存储空间应消除*/
          i--;
      printf("%s - %s =\n", p, q);
         for(j=i; j>=0; j--)
          printf("%d",a[j]);
   }  
   else/*若m小于n,则按n-m计算,输出结果前面加负号*/
      {
      for(i=0; i<len2; i++)
      {
         if(b[i] >= a[i])
             b[i]=b[i]-a[i];
         else
         {
            b[i+1]-=1;
            b[i]=b[i]+10-a[i];
         }   
      }  
      while(b[i] == 0)/*用j表示现有数字的个数,多出的存储空间应消除*/
          i--;
      printf("%s - %s =\n", p, q);
      printf("-");
         for(j=i; j>=0; j--)
          printf("%d",b[j]);
   }  
}

int PanDuan( int len)
{
   int i=len;
   while(a[i] >= b[i] && i >= 0)
       i--;
      if(i >= 0)
          return 0;
   else if((i < 0) && (a[i+1] == b[i+1]))
      {
         printf("\nThe answer is 0");
         system("pause");
      exit(0);
   }   
   else
       return 1;
}       

我来回复

您尚未登录,请登录后再回复。点此登录或注册