所谓的高精度运算,是指参与运算的数(加数,减数,因子……)范围大大超出了标准数据类型(整型,实型)能表示的范围的运算。例如,求两个200位的数的和。这时,就要用到高 精度算法了。在这里,我们先讨论高精度加法。高精度运算主要解决以下三个问题:
基本方法
1、加数、减数、运算结果的输入和存储
运算因子超出了整型、实型能表示的范围,肯定不能直接用一个数的形式来表示。能表示多个数的数据类型有两种:数组和字符串
(1)数组:每个数组元素存储1位(在优化时,这里是一个重点!),有多少位就需要多
少个数组元素;
用数组表示数的优点:每一位都是数的形式,可以直接加减;运算时非常方便
用数组表示数的缺点:数组不能直接输入;输入时每两位数之间必须有分隔符,不符合数
值的输入习惯;
(2)字符串:字符串的最大长度是255,可以表示255位。
用字符串表示数的优点:能直接输入输出,输入时,每两位数之间不必分隔符,符合数值
的输入习惯;
用字符串表示数的缺点:字符串中的每一位是一个字符,不能直接进行运算,必须先将它
转化为数值再进行运算;运算时非常不方便;
(3)因此,综合以上所述,对上面两种数据结构取长补短:用字符串读入数据,用数组存
储数据:
#include <stdio.h>
#include <assert.h>
#include <string.h>
#define max_strlen 100
void convert(char *num)
{
assert(num!=NULL);
int strlent=strlen(num);
int temp=0;
for (int i=0;i<=(strlent-1)/2;i++)
{
temp=num[i];
num[i]=num[strlent-1-i];
num[strlent-1-i]=temp;
}
}
void addbig(const char *num1, const char *num2,char *result)
{
assert(num1!=NULL && num2!=NULL);
char *num11=(char*)num1;
char *num22=(char*)num2;
int len1=strlen(num1);
int len2=strlen(num2);
convert(num11);
convert(num22);
int len=(len1>=len2)?len1:len2;
int ret[max_strlen];
memset((void*)ret,0,max_strlen*sizeof(int));
for (int i=0;i<len;i++)
{
if (i>=len1)
{
num11[i]='0';
}
if (i>=len2)
{
num22[i]='0';
}
ret[i]+=(int)(num11[i]-'0')+(int)(num22[i]-'0');
if (ret[i]>=10)
{
ret[i]=ret[i]%10;
ret[i+1]++;
}
}
if (ret[len]==1)
{
len=len+1;
}
for (int j=len-1;j>=0;j--)
{
result[len-1-j]=*((char*)(ret+j))+'0';
}
}
void main()
{
char n1[100]="23463367805678967878945";
char n2[100]="23568484567476567";
char result[100]="";
addbig(n1,n2,result);
puts(result);
}
其中,有几点需要注意的地方:
1,void *memset( void *dest, int c, size_t count ); count:Number of characters,所以当内存区域存放的是整型时,需要写为len*sizeof(int),才能将这一块内存区域置0.
2,if (i>=len1)
{
num11[len1-1-i]='0';
}
是为了防止当i>=len1时,num[11]='\0 ',ASCII码的值为零,并不是字符'0',要注意区分!!!
3,将数字转化成为字符串时,要加‘0’。
4,convert函数是将字符串反转,不然的话,如果不反转,从最后一个数开始,一直往前的话, 要判断字符串是否结束,否则就会出现字符串越界的现象。
附:栈中能操作的一段称为栈顶,不能操作的一段称为栈底,栈是由高地址向低地址生长的,所以栈底的地址要高于栈顶的地址。