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

专题篇:高精度

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

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

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

高精度计算是一种用来处理大数据的算法,一般超过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
选择需要的高精计算,删除注释即可。
——————————————————————我是讲废话的分割线———————————————————————

猜你喜欢

转载自blog.csdn.net/prasnip_/article/details/78823870