【第七篇blog】专题:高精度计算<上>

来源:互联网 发布:网络视频节目许可证 编辑:程序博客网 时间:2024/06/06 12:48

专题篇:高精度

——————————————————————我是更新提示分割线———————————————————————

<第一次更新>仅供学习使用

—————————————————————我是华丽丽的正文分割线——————————————————————

高精度计算是一种用来处理大数据的算法,一般超过longlong的数据计算就需要使用高精度算法,上篇主要讲加法和减法。

加法

引入:A+B Problem
题目描述

高精度加法,相当于a+b problem,不用考虑负数
输入输出格式
输入格式:

分两行输入a,b<=10^1000

输出格式:

输出只有一行,代表A+B的值

解析:看似简单的题目,但数据量非常大,这时,就不可能用直接计算来实现了。
思考1):怎样储存数据?
对于大数据,可以采用字符串输入,转换为数组储存,每一个下标所在的位置储存一位数字,就可以方便的储存大数据了。
因此,我们有如下函数代码:

void scan(){    cin>>s>>s1;    for(i=0;i<=s.size();i++)a[i]=int(s[i]-'0');//将字符的数字转换为数字的值    for(i=0;i<=s1.size();i++)b[i]=int(s1[i]-'0');}

思考2):怎样计算?
对于计算,有了数组储存,我们很容易就能想到逐位相加,实际就是模拟我们小学中的列竖式计算。
但是,如果使用这种计算方式,对于最高位储存在最前面的数组,进位的处理就会变得相当麻烦,必须将储存方式推翻重来

所以,储存方式为逆序储存,方便进位处理。又有如下代码

void scan(){    cin>>s>>s1;    for(i=0;i<=s.size();i++)a[s.size()-i]=int(s[i]-'0');//将当前数字储存到a,b数组的末端    for(i=0;i<=s1.size();i++)b[s1.size()-i]=int(s1[i]-'0');}

这样,我们就能实现计算的基本代码了

void initi(){    for(i=1;i<=1001;i++)    {        c[i]=b[i]+a[i];    }   }

思考3):怎样处理进位?
对于进位,直接采用数组的求余,加减就很容易实现
计算代码能做如下更改

void initi(){    for(i=1;i<=1001;i++)    {        c[i]=c[i]+b[i]+a[i];        c[i+1]=c[i]/10;//进位处理:当然,c[i]不足10时,c[i]/10=0,c[i]%10=c[i]        c[i]=c[i]%10;    }   }

到这里为止,高精度加法的计算已经大体实现,最后一步时输出,不要忘记储存时是逆序储存的,输出时去掉数组末尾的0,逆序输出即可
代码如下

void print(){    while(c[maxx]==0&&maxx>1)maxx--;    for(i=maxx;i>=1;i--)    {        cout<<c[i];    }}

将各个函数组合,高精度加法的代码就能实现了

#include<bits/stdc++.h>using namespace std;int i,j,maxx=1001;string s,s1;int a[1050]={},b[1050]={},c[1050]={};void scan()//输入{    cin>>s>>s1;    for(i=0;i<=s.size();i++)a[s.size()-i]=int(s[i]-'0');    for(i=0;i<=s1.size();i++)b[s1.size()-i]=int(s1[i]-'0');}void initi()//计算{    for(i=1;i<=1001;i++)    {        c[i]=c[i]+b[i]+a[i];        c[i+1]=c[i]/10;        c[i]=c[i]%10;    }   }void print()//输出{    while(c[maxx]==0&&maxx>1)maxx--;    for(i=maxx;i>=1;i--)    {        cout<<c[i];    }}int main(){    scan();    initi();    print();    return 0;}

减法

引入:A-B Problem
输入输出格式
输入格式:

两个整数a,b(第二个可能比第一个大)

输出格式:

结果(是负数要输出负号)

对于高精度减法,又有几个新的问题
思考1):怎样处理负数?
对于负数的处理,如果b>a,我们能直接输出一个负号,再交换a,b进行计算即可。
因此,我们首先需要一个比较两个高精度数的大小的函数,思路就是先比较长度,如果相同,再从高位到低位逐位比较。

int bigger(int k,int l)//k,l代表s1,s2的当前比较位{    if(k==1&&l==1&&s1[k]==s2[l])return 0;    if(s1.size()>s2.size())return 1;    else    {        if(s2.size()>s1.size())return 2;        else        {            if(s1[k]>s2[l])return 1;            else            {                if(s2[l]>s1[k])return 2;                else                {                    return bigger(k-1,l-1);                }            }        }    }} //返回1代表s1大,返回2代表s2大,返回0代表两数完全相等

这样,我们就能构成交换函数了

void change(){    if(bigger(s1.size(),s2.size())==2)//比较两数    {        cout<<"-";        s3=s1;        s1=s2;        s2=s3;    }}

思考2):怎样处理借位?
借位的处理实际和进位相似,只需将当前位加10,下一位减1即可

void initi(){    for(i=1;i<=s1.size();i++)    {        c[i]=c[i]+a[i]-b[i];        if(c[i]<0)//借位处理        {            c[i]+=10;            c[i+1]--;        }    }}

处理完这两个问题,高精度减法也基本完成了,组合输入输出就能构成代码。

#include<bits/stdc++.h>using namespace std;int i,j,maxx=10005;string s1,s2,s3;int a[10005]={},b[10005]={},c[10005]={};void scan()//输入{    cin>>s1>>s2;    for(i=0;i<=s1.size();i++)a[s1.size()-i]=int(s1[i]-'0');    for(i=0;i<=s2.size();i++)b[s2.size()-i]=int(s2[i]-'0');}int bigger(int k,int l)//比较{    if(k==1&&l==1&&s1[k]==s2[l])return 0;    if(s1.size()>s2.size())return 1;    else    {        if(s2.size()>s1.size())return 2;        else        {            if(s1[k]>s2[l])return 1;            else            {                if(s2[l]>s1[k])return 2;                else                {                    return bigger(k-1,l-1);                }            }        }    }} void change()//交换{    if(bigger(s1.size(),s2.size())==2)    {        cout<<"-";        s3=s1;        s1=s2;        s2=s3;    }}void print()//输出{    while(c[maxx]==0&&maxx>1)maxx--;    for(i=maxx;i>=1;i--)    {        cout<<c[i];    }}void initi()//计算{    for(i=1;i<=s1.size();i++)    {        c[i]=c[i]+a[i]-b[i];        if(c[i]<0)        {            c[i]+=10;            c[i+1]--;        }    }}int main(){    change();    scan();    initi();    print();    return 0;}

到此为止,高精度的简单计算:加法,减法就实现了。
—————————————————————我是华丽丽的正文分割线——————————————————————

提示:下篇讲高精乘除
附件:高精运算模板,用于验证自己的程序是否准确
链接:https://pan.baidu.com/s/1bo9YN87
password:p0du
选择需要的高精计算,删除注释即可。
——————————————————————我是讲废话的分割线———————————————————————

原创粉丝点击