前一章将遇到了A+B>C的问题,具体如下:给定区间[-2^31^, 2^31^]内的3个整数A、B和C,请判断A+B是否大于C。因为范围只有2^32,所以可以用long long 或者double 解决,可问题来了,要是数据大于2^63-1,怎么办?8个字节处理不了。这个时候就必须自己构造一种数据类型来存放该数。下面分析一下大数的数据类型该如何定义(个人心得,有更好的方法欢迎互相交流):
1、首先想到的是链表与数组,可是链表有一个问题,那就是太“灵活”了,数据的长度可以随时改变,不好处理。因此,必须使大数的数据长度是固定的。我选择了字符串数组,为什么不用int 数组呢?没必要,浪费内存;当然也可以使用。
2、然后就得定义大数高位、低位在数组中存放的方式了,我选择的是高位在高字节、低位在低字节。同时高位补零‘0’,还有不能忘了字符串最后一位定义为‘\0’。
3、由于上述定义不能通过字符串函数输出,因此需要先确定长度,再输出,需要定义返回长度的函数。
4、加法运算,减法运算、乘法运算如果不是正整数,必须需要判断正负,再写出正整数的加减乘函数即可。注意函数不能返回,只能通过形参传递。
具体实现:
#include <stdio.h>
#include <string.h>
#define Length 5*8+1
void LInput(char *a); /* 大数输入 */
void LOutput(char *a); /* 大数输出 */
int StrLen(char *a); /* 求大数长度 */
int Compare(char *a,char *b); /* a>=b 返回1,否则返回0 */
int Compare(char *a,char *b); /* a>=b 返回1,否则返回0 */
void fun1(char *a,char *b,char *t); /* 大数为正相加 */
void fun2(char *a,char *b,char *t); /* 大数为正相减 */
void LAdd(char *a,char *b,char *c); /* 大数相加 */
void LSub(char *a,char *b,char *c); /* 大数相减 */
void LMul(char *a,char *b,char *c); /* 大数相乘 */
int main()
{
char a[Length],b[Length],c[Length]; /* 字符串数组存储大数 */
LInput(a);
LInput(b);
// LAdd(a,b,c);
// LSub(a,b,c); /* 大数相减 */
LMul(a,b,c); /* 大数相乘 */
LOutput(c);
// LDiv(a,b); /* 大数相除 */
return 0;
}
void LInput(char *a) /* 大数输入,最高位前面的初始化为'0' */
{
int i,j;
char t;
for(i=0;i<Length;i++)
{
scanf("%c",&a[i]);
if(a[i]=='\n' || a[i]==' ')
{
j=i-1; /* 记住输入字符长度 */
while(i<Length) a[i++]='0'; /* 补零 */
break;
}
}
if(i==Length) a[i-1]='\0'; /* 字符串最后一位'\0' */
/* 逆序,高位存储在高字节 */
for(i=0;i<=j;i++,j--)
{
t=a[i];
a[i]=a[j];
a[j]=t;
}
}
void LOutput(char *a) /* 大数输出 */
{
int j=StrLen(a)-1;
if(a[0]=='\0') printf("溢出\n");
if(j==-1) printf("%d",a[j]); /* 0 的情况 */
else
for(;j>=0;j--)
printf("%c",a[j]);
}
int StrLen(char *a) /* 求大数长度,包括正负号 */
{
int i;
while(*a) a++; /* 从后序开始查找 */
for(i=0;;i++)
if(*--a !='0') break;
return Length-i-1;
}
int Compare(char *a,char *b) /* a>b 返回1,否则返回0 */
{
int L1=StrLen(a)-1,L2=StrLen(b)-1;
char a1[Length],a2[Length],i;
/* a>=0,b<0 */
if(a[L1]!='-' && b[L2]=='-')
return 1;
/* a<0,b>=0 */
if(a[L1]=='-' && b[L2]!='-') return 0;
/* a<0,b<0 */
for(i=0;i<Length;i++) /* 先存储,再使用,防止a,b的值被改变 */
{
a1[i] = a[i];
a2[i] = b[i];
}
if((a[L1] == '-') && (b[L2] == '-'))
{
a1[L1]=a2[L2]='0';
if(PCompare(a1,a2)) return 0;
else return 1;
}
/* a>=0,b>=0 */
return PCompare(a1,a2);
}
int PCompare(char *a,char *b) /* a,b均大于0,a>b 返回1,否则返回0 */
{
int l1=StrLen(a)-1,l2=StrLen(b)-1;
if(l1>l2)
return 1;
if(l1<l2)
return 0;
for(;l1>=0;l1--)
{
// printf("a[%d]=%c,b[%d]=%c\n",l1,a[l1],l1,b[l1]);
if(a[l1]>b[l1]) return 1;
if(a[l1]<b[l1]) return 0;
}
return 0;
}
void LAdd(char *a,char *b,char *c) /* 大数相加 */
{
int L1=StrLen(a)-1,L2=StrLen(b)-1,l;
/* a>0,b>0,a+b */
if(a[L1]!='-' && b[L2]!='-')
fun1(a,b,c);
/* a>0,b<0,转化成a-|b| */
if(a[L1]!='-' && b[L2]=='-')
{
b[L2]='0';
if(Compare(a,b)) /* 若a>=|b|,则a-|b|,否则-(|b|-a) */
fun2(a,b,c);
else
{
fun2(b,a,c);
c[StrLen(c)]='-';
}
}
/* a<0,b>0,转化成b-|a| */
if(a[L1]=='-' && b[L2]!='-')
{
a[L1]='0';
if(Compare(b,a)) /* 若b>=|a|,则b-|a|,否则-(|a|-b) */
fun2(b,a,c);
else
{
fun2(a,b,c);
c[StrLen(c)]='-';
}
}
/* a<0,b<0,转化成-(|b|+|a|) */
if(a[L1]=='-' && b[L2]=='-')
{
a[L1]='0';
b[L2]='0';
fun1(a,b,c);
l=StrLen(c);
c[l]='-';
}
}
void fun1(char *a,char *b,char *t) /* 大数为正相加 */
{
int i,c=0,s; /* c进位 */
for(i=0;i<Length;i++)
{
s = a[i]-'0'+b[i]-'0';
if(s<10)
{
t[i]=s+'0'+c;
c=0;
}
else
{
t[i]=s-10+'0'+c;
c=1;
}
}
if(c == 1) /* 最高位进位,溢出 */
t[0] = '\0';
else
t[i-1] = '\0';
}
void fun2(char *a,char *b,char *t) /* 大数为正相减,且a>b */
{
int i,c=0,s; /* c借位 */
for(i=0;i<Length;i++)
{
s = a[i]-'0'-(b[i]-'0');
if(s>=0)
{
t[i]=s+'0'-c;
c=0;
}
else
{
t[i]=s+10+'0'-c;
c=1;
}
}
if(c == 1) /* 最高位借位,溢出 */
t[0] = '\0';
else
t[i-1] = '\0';
}
void LSub(char *a,char *b,char *c) /* 大数相减 */
{
int L1=StrLen(a)-1,L2=StrLen(b)-1,l;
/* a>0,b>0,a-b */
if(a[L1]!='-' && b[L2]!='-')
if(Compare(a,b)) /* 若a>=b,a-b,否则-(b-a)*/
fun2(a,b,c);
else
{
fun2(b,a,c);
c[StrLen(c)]='-';
}
/* a>0,b<0,转化成a+|b| */
if(a[L1]!='-' && b[L2]=='-')
{
b[L2]='0';
fun1(a,b,c);
}
/* a<0,b>0,转化成-(b+|a|) */
if(a[L1]=='-' && b[L2]!='-')
{
a[L1]='0';
fun1(a,b,c);
l=StrLen(c);
c[l]='-';
}
/* a<0,b<0,转化成|b|-|a| */
if(a[L1]=='-' && b[L2]=='-')
{
a[L1]='0';
b[L2]='0';
if(Compare(b,a)) /* 若|b|>=|a|,则|b|-|a|,否则-(|a|-|b|) */
fun2(b,a,c);
else
{
fun2(a,b,c);
c[StrLen(c)]='-';
}
}
}
void fun3(char *a,char *b,char *c) /* 大数为正数相乘 */
{
int i,j,k,ct=0,s; /* ct进位 */
char t[Length];
char *a1,*a2;
if(Compare(a,b)) { /* 使a*b满足a>b */
a1=a;
a2=b;
}
else{
a1=b;
a2=a;
}
for(i=0;i<Length;i++) /* 字符串初始化 */
c[i]=t[i]='0';
c[i-1]=t[i-1]='\0';
for(i=0;i<StrLen(a2);i++)
{
for(k=0;k<i;k++) /* 前i个字符初始化为'0' */
t[k]='0';
for(j=0;j<StrLen(a1);j++)
{
s = (a2[i]-'0')*(a1[j]-'0')+ct; /* 乘法公式 */
t[k+j]=s%10+'0';
ct=s/10; /* 进位 */
}
t[k+j]=ct+'0';
fun1(t,c,c); /* c+=k */
}
if(StrLen(a)+StrLen(b)>Length-1) c[0]='\0'; /* 溢出 */
}
void LMul(char *a,char *b,char *c) /* 大数相乘 */
{
int L1=StrLen(a)-1,L2=StrLen(b)-1,l;
/* a>0,b>0,a*b */
if(a[L1]!='-' && b[L2]!='-')
fun3(a,b,c);
/* a>0,b<0,转化成-a*|b| */
if(a[L1]!='-' && b[L2]=='-')
{
b[L2]='0';
fun3(a,b,c);
l=StrLen(c);
c[l]='-';
}
/* a<0,b>0,转化成-|a|*b */
if(a[L1]=='-' && b[L2]!='-')
{
a[L1]='0';
fun3(a,b,c);
l=StrLen(c);
c[l]='-';
}
/* a<0,b<0,转化成|b|*|a| */
if(a[L1]=='-' && b[L2]=='-')
{
a[L1]='0';
b[L2]='0';
fun3(a,b,c);
}
}