利用计算机进行数值计算,有时会遇到这样的问题:
有些计算要求精度高,希望计算的数的位数可达几十位甚至几百位,虽然计算机的计算精度也算较高了,但因受到硬件的限制,往往达不到实际问题所要求的精度。这时候我们就需要高精度算法。这里介绍C语言高精度加法的实现。
加数超出了整型、实型能表示的范围,肯定不能直接用一个数的形式来表示。在运算过程中,能表示多个数的数据类型有两种:数组和字符串。
(1)数组:每个数组元素存储1位(在优化时,这里是一个重点!),有多少位就需要多少个数组元素;用数组表示数的优点:每一位都是数的形式,可以直接加减,运算时非常方便;用数组表示数的缺点:数组不能直接输入;输入时每两位数之间必须有分隔符,不符合数值的输入习惯;
(2)字符串:字符串的最大长度是多少,可以表示多少位数字?用字符串表示数的优点:能直接输入输出,输入时,每两位数之间不必分隔符,符合数值的输入习惯;用字符串表示数的缺点:字符串中的每一位是一个字符,不能直接进行运算,必须先将它转化为数值再进行运算;运算时非常不方便;
(3)因此,综合以上所述,对上面两种数据结构取长补短:用字符串读入数据,用数组存储数据。
列竖式计算35+86。
正常计算过程:
(1)运算顺序:两个数靠右对齐;从低位向高位运算;先计算低位再计算高位;
(2)运算规则:同一位的两个数相加再加上从低位来的进位,成为该位的和;这个和去掉向高位的进位就成为该位的值;如上例:3+8+1=12,向前一位进1,本位的值是2;可借助取余、整除运算完成这一步;
(3)最后一位的进位:如果完成两个数的相加后,进位位值不为0,则应添加一位;
(4)如果两个加数位数不一样多,则按位数多的一个进行计算;
编程思路:
确定a和b中的最大位数x(x=max(lena,lenb))
依照由低位至高位(第1位至第x位)的顺序进行加法运算。
在每一次的运算中,a当前位加b当前位的和除以10,其商即为进位,其余数即为和的当前进位。
在进行了x位的加法后,若最高位有进位(a[x+1]<>0),则a的长度为x+1。
int main ()
{
//利用字符串形式输入,否则数字太大,整形放不下。
char a[505]="123",b[505]="123";
//初始化为0,这对后面循环体中的运算很关键
int arr1[505]={0},arr2[505]={0};
//输入数字字符串
scanf("%s",&a);scanf("%s",&b);
int lena=strlen(a);int lenb=strlen(b);
//取lena,lenb中的最大值,考虑进位,加1,作为加法主体循环条件
int x;
if(lena>lenb) x=lena+1;
else x=lenb+1;
//将字符串转变为数组形式,转置高低位存储
for(int i=0;i<lena;i++)
{
//转为数字后,存储顺序转置
//即自然数高位在前低位在后
//相加时低位先加放前面,高位放后面
//如:a[0]是最高位,放在最后面arr1[lena]位置
arr1[lena-i]=a[i]-'0';
}
for(int i=0;i<lenb;i++)
{
arr2[lenb-i]=b[i]-'0';
}
//高精度加法主体
for(int i=1;i<=x;i++)
{
//竖式计算,从低位起,相同位相加
arr1[i]=arr1[i]+arr2[i];
//相加的结果溢出的进位
arr1[i+1]=arr1[i+1]+arr1[i]/10;
//取出相加结果的余数
arr1[i]=arr1[i]%10;
}
//删除前导0,即高位前面的无效0
if(arr1[x]==0&&x>0) x--;
//输出要反向,从高位先输出
for(int i=x;i>0;i--)
{
printf("%d",arr1[i]);
}
return 0;
}
运算结果示例: