高精度

整理一下高精度

对于不会高精度的人而言,那么必然有一道题让你印象深刻,阶乘之和

明明自己写的很对,明明样例过去了,但是问题在于,就是只能拿到一半的分数,这究竟是什么原因呢?

看一下数据范围 并没有

总之,反正,这道题只有使用高精度才能过去。

其实也并不一定:

#include<iostream>
using namespace std;
string a[60]={"0","1","3","9","33","153","873","5913","46233","409113","4037913","43954713","522956313","6749977113","93928268313","1401602636313","22324392524313","378011820620313","6780385526348313","128425485935180313","2561327494111820313","53652269665821260313","1177652997443428940313","27029669736328405580313","647478071469567844940313","16158688114800553828940313","419450149241406189412940313","11308319599659758350180940313","316196664211373618851684940313","9157958657951075573395300940313","274410818470142134209703780940313","8497249472648064951935266660940313","271628086406341595119153278820940313","8954945705218228090637347680100940313","304187744744822368938255957323620940313","10637335711130967298604907294846820940313","382630662501032184766604355445682020940313","14146383753727377231082583937026584420940313","537169001220328488991089808037100875620940313","20935051082417771847631371547939998232420940313","836850334330315506193242641144055892504420940313","34289376947494122614363304694584807557656420940313","1439295494700374021157505910939096377494040420940313","61854558558074209658512637979453093884758552420940313","2720126133346522977702138448994068984204397080420940313","122342346998826717539665299944651784048588130840420940313","5624964506810915667389970728744906677010239883800420940313","264248206017979096310354325882356886646207872272920420940313","12678163798554051767172643373255731925167694226950680420940313","620960027832821612639424806694551108812720525606160920420940313","31035053229546199656252032972759319953190362094566672920420940313"};
int main()
{
    int n;
    cin>>n;
    cout<<a[n];
}

打表万岁 手动划掉

依然回归正题,也就是我们的标题——高精度

利用计算机进行数值计算,有时会遇到这样的问题:有些计算要求精度高,希望计算的位数可达几十位甚至几百位,虽然计算机的计

算精度也算较高了,但因受硬件的限制,往往达不到实际问题所要求的精度。我们可以利用程序设计的方法去实现这样的高精度计算。

相信大家一定能够记得,我们在学习比较大的数的加法和减法的时候,经常使用一个东西——竖式。

那么。

对于高精度的加法和减法而言,我们是不是同样可以使用竖式的思路进行操作呢。

显然,我们只需要开两个数组,分别存储加数和被加数,然后按位进行相加。

但是需要注意两个问题

第一、注意进位操作

第二、在进行相加操作的时候一定要按位相加

那么,代码如何实现呢?

加法进位

c[i]=a[i]+b[i];
if(c[i]>=10) {c[i]%10;++c[i+1]}

同理,减法借位

if(a[i]<b[i]) {--a[i+1];a[i]+=10}
c[i]=a[i]-b[i];

注意,与加法相比,减法的借位是在进行减法操作之前(不然会出现负数,这显然不是我们希望看到的),而加法的进位要在进行加法操作之前(不然我怎么知道需要进位呢?)

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
char aa[101],bb[101];
int a[101],b[101],c[101],lena,lenb,lenc;//将数组开在主函数外面,因为我懒得初始化
int main(){
  gets(aa);
  gets(bb);
  lena=strlen(aa);
  lenb=strlen(bb);//读取字符串的长度,便于加法循环的结束
  for(int i=0;i<=lena;i++){
    a[lena-i]=aa[i]-48;//'0'=48,此处操作意味着把aa数组内的数转成int型
  }
  for(int i=0;i<=lenb;i++){
    b[lenb-i]=bb[i]-48;//或许有的人会对这里(当然上面也一样)有疑惑,这里其实是倒着把字符串读入数组,以便实现相同位的对齐
  }
  lenc=1;
  x=0;
  while(lenc<=lena||lenc<=lenb){
    c[lenc]=a[lenc]+b[lenc]+x;
    x=c[lenc]/10;
    c[lenc]%=10;
    lenc++;
  }
  c[lenc]=x;
  if(c[lenc]==0) lenc--;
  for(int i=1;i>=1;i--){
    cout<<c[i];//得到的结果是倒着的,于是要倒着输出数字,形成正着的结果
  }
  return 0;
}

大家可以自行思考一下高精度减法的写法。

相信我,我绝对没有忘记 阶乘之和

我们可以明确的是,

阶乘之和需要用到的是高精度乘低精度,

但是我们显然不能满足于此,

于是,我们选择写:

高精度乘法!!!

高精度乘高精度

类似加法,可以用竖式求乘法。

同样的依然需要考虑进位。

同时对每一位进行乘法运算时,必须进行错位相加。

大家自己想一想写竖式乘法的时候,第二个式子是要提前一位的。

那么,构思一下代码……

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
char aa[101],bb[101];
int a[101],b[101],c[10001],lena,lenb,lenc;
int main(){
  scanf("%s",aa);
  scanf("%s",bb);
  lena=strlen(aa);
  lenb=strlen(bb);
  for(int i=0;i<=lena-1;i++){
    a[lena-i]=aa[i]-48;
  }
  for(int i=0;i<=lenb;i++){
    a[lenb-i]=bb[i]-48;
  }
  for(int i=1;i<=lena;i++){
    x=0;
    for(int j=1;j<=lenb;j++){
      c[i+j-1]=a[i]*b[i]+x+c[i+j-1];
      x=c[i+j-1]/10;
      c[i+j-1]%10;
    }
    c[i+lenb]=x;
  }
  lenc=lena+lenb;
  while(c[lenc]==0&&lenc>1) lenc--;
  for(int i=lenc;i>=1;i--){
    cout<<c[i];
  }
  return 0;
}

为了培养大家自己思考的能力,所以没有注释。

绝对不是因为我懒!!! 划掉

另外,我是绝对不会告诉你们我把上面自己打的高精度写法复制进洛谷里面wa了三次的

相信有了高精度乘法的基础,大家就不需要我把阶乘之和的代码贴在下面了吧!

所以,大家加油!!!

在最后,我们补充一下高精度除法,确切的说,是高精度除以低精度。

做除法时,每一次的商都在0~9,每次求得的余数连接以后的若干位得到新的被除数,继续做除法。

因此,在做高精度出发是,要涉及到乘法运算和减法运算,还要有位移处理。

当然,为了程序简洁,可以避免高精度乘法,用0~9此循环减法取代得到商的值。

对于高精度数除以单精度数哦结果,采取的方法是按位相除法。

代码就不放了!!!大家自己思考

(上文部分内容引用自《信息学奥赛一本通》(小黄书))

——by 某个不知名的精分患者

posted @ 2020-09-15 19:35  Luo_Feng_Han  阅读(385)  评论(1编辑  收藏  举报