高精度算法(C++)

当我们利用计算机进行数值计算,有时候会遇到这样的问题: n! 的精确结果是多少?
当n小于30的时候,我们当然可以通过电脑自带的计算器计算出来。但是当我们遇到 100! 的时候就没有办法直接计算出精确的结果。
这是由于计算机的特点是运算速度超级快精确度高,因此利用计算机进行高精度的计算和处理是计算机的一个重要应用。所谓高精度运算,是指参与运算的数(加数,减数,因子……)范围大大超过了标准数据类型(整型,实型)能表示的范围的运算。
(注:①n!=1 * 2 * 3 * ……* (n-1) * n ,例如 5!=1 * 2 * 3* 4 * 5 = 120 )
高精度处理,实际上就是模拟法,模拟手算,它的原理与我们用竖式计算时一样的,不过在处理过程中要注意高精度数据的读入、转换储存、数据的计算、结果位数的计算、输出等几个问题。

高精度计算中需要处理如下几个问题:

(1)数据的输入
数据的输入,需要考虑输入的位数问题(可能上百上千位),也要考虑输入的数可能带字母(可能是16进制)等问题。所有我们选用字符串输入。

string s;
cin>>s;

若输入的数据可能有负数,就加上下面的语句,删掉第一个字符,记录负号。

if(s[0]==‘-’) 
{
s.erase(0,1);          //erase是字符串中的删除,s.erase(0,1)表示在0位置删除1个字符
fuhao=-1;
}

———————————————————————————————————————————

(2)数据的转换储存
数据是通过字符串输入的,不能够直接进行计算,需要转换成数字。我们选用最基本的转换储存方式,字符串的一个字符对应数组中的一个元素,把字符串的数字全部转换到一个数组中,其中数组下标为1对应输入数的个位,数组下标为2的对应输入数的十位,以此类推。

int a[10002];                  //建议放在全局变量,默认为0。也可以用memset函数清0;
len=s.size();                 //len表示输入的数据的位数
for(i=1;i<=len;i++)
a[i]=s[len-i]-48;       	//将数串s转换为数组a,并倒序存储。

如果数据是16进制的,还需要补充一句:

if(a[i]>=10)a[i]=a[i]-7;

通过这样,我们就可以把输入的数据很好的放入数组当中了。

———————————————————————————————————————————

(3)数据的计算

①加法
两大正整数相加,a数组=a数组+b数组(注:a[1]表示a数据的个位)
对应位置相加并加上低位的进位数。得到的新数字如果超过9,把个位留下,高位进上去。

x=0;
for(i=1;i<=10000;i++)       	//最终结果不超过10000位的整数的加法
{
a[i]=a[i]+b[i]+x;
x=a[i]/10;
a[i]=a[i]%10;
}

②减法
两大正整数相减,a数组=大a数组-小b数组
模拟普通的减法,从低位开始对应的减,不足就向高位借一。

for(i=1;i<=10000;i++)	      //一万位以内的整数的减法
{
if(a[i]<b[i])
{
a[i]+=10;
a[i+1]--;
}
a[i]=a[i]-b[i];
}

③乘法
这里有2种方法:

1
一大正整数乘以小正整数,a数组=a数组*k;
同加法类似,每一位都乘以k,再加上之前的进位,如果新得到的数字超过了10,哪么个位留下,高位进上去。

x=0;
for(i=1;i<=10000;i++)		//最终结果不超过10000位
{
a[i]=a[i]*k+x;
x=a[i]/10;
a[i]=a[i]%10; 
}

2
两大正整数相乘,c数组=a数组*b数组
模拟普通乘法。

x=0;
for(i=1;i<=lena+1;i++)	        //lena为a的数位
for(j=1;j<=lenb+1;j++)	       //lenb为b的数位
{
c[i+j-1]=a[i]*b[j]+x+c[i+j-1]; 
x=c[i+j-1]/10;
c[i+j-1]=c[i+j-1]%10;
}

④除法
这里也有2种方法:

1
大正整数除以小正整数,c数组=a数组÷b数

x=0;
for(i=1;i<=len;i++)	         //a的数位
{
c[i]=(x*10+a[i])/b;
x=(x*10+a[i])%b;
}

2
两大正整数相除,c数组=a数组÷b数组
见下面的例5

———————————————————————————————————————————

(4)结果位数的计算

len=10000;					//取最高位
while(a[len]==0) 
len--;	                  //最高位为0时候就舍去

如果结果可能为0,就需要改成:

while(a[len]==0&&len>1) 
len--;

(5)结果的输出

for(i=len;i>=1;i--)
cout<<a[i];

天哪,我竟然打了这么多字!!??
总而言之,打字不易,知识点还需要你自己去巩固和加深,为了一篇详细的文章,我手都软了。
哦,对了,还有一点我差点忘了:

求大家关注我的博客,谢谢qwq。
戳我看看手废作者的博客

  • 16
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值