C++中高精度运算总结

目录

一.产生原因

二.不同方法介绍

三.模拟过程(核心代码)

1.加法(进位)

 2.减法(借位)

 3.乘法(高精度a*低精度b)

4.除法(高精度a÷低精度b)

四.完整代码

1.加法

2.减法

3.乘法

4.除法 


一.产生原因

首先明确为什么有高精度运算即大数的运算。由于C++中最大的long long也只能存到2^63-1=9223372036854775807(19位数),但当数字长度接近10^5甚至更长时就没办法用long long储存了,所以不能直接对变量进行加减,因此有了高精度算法,最近我刚学,怕忘就总结了一下,仅供参考,如有错误还请指正。

对了:题目指路

加法:https://www.acwing.com/problem/content/793/

减法:https://www.acwing.com/problem/content/794/

乘法:https://www.acwing.com/problem/content/795/

除法:https://www.acwing.com/problem/content/796/

二.不同方法介绍

高精度算法一般有两种形式,①数组模拟    ②用STL中的vector容器 。

 ①:将字符串string中的每一位转化为int数组中的数;

②:用vector中

的函数push_back();  pop_back();  back(); front();  begin();  进行操作;

两者的模拟加法的大致思想是一样的,但STL容器可以在空间上随用随申请,而数组只能提前申请(a[100010])固定空间。

三.模拟过程(核心代码)

1.加法(进位)

C++中高精度运算总结_第1张图片

这个是平时咱们计算的过程(红1表示进位)而写程序时咱们需要找到一个循环起来的方法,于是继续思考我们为什么会知道进位以及进多少

C++中高精度运算总结_第2张图片

上图为直接对每一位相加之后的结果,从最低位(个位)看起,就可以发现8=18%10,9=(18+1)%10,1=(0+1)%10。这样就找到规律了:

每一位上的数字=(进位+加数上同位两数字的和)%10

进位=(进位+加数上同位两数字的和)/10 

:这里是默认的a的长度>b的长度!

(数组模拟,rr[]为结果)

for(int i=0; i=10)  rr[i+1]++,rr[i]-=10;
}
if(rr[len])  len++;//这里处理a+b后最高位的进位问题

:这里一定要分两个for来加和判断,要不然循环第二次进行时会覆盖++,进位就没有用到!

等等,写到这里我突然意识到只要把res那改成+=就可以了!妙蛙!

for(int i=0; i=10)  rr[i+1]++,rr[i]-=10;
}

 (vector)

for(int i=0; i

 2.减法(借位)

从结果上来看a-b可能是正数可能是负数,负数时加上符号变成b-a即可,这里不再赘述。

比较简单的情况是被减数的每一位都恰好比减数的每一位大,这里就不列举了;

比较复杂的就是下图这样有借位的情况:

C++中高精度运算总结_第3张图片

还是和加法一样先对每一位做减法(红字),然后从低位(个位)开始考虑借位变成下图(蓝字)

        C++中高精度运算总结_第4张图片

 就可以找到规律:

每一位上的数字=同位减法,判断是否<0,小于则下一位(高位)--,本位+=10

Or:

每位数字=(同位减法+10-标记)%10,如果减法<0则标记1,否则标记0

(这个标记是在下一位(高位)时才开始起作用,模拟借位的过程,先判断有没有被借过位)

 :这里默认a>b!

(数组)

for(int i=0; i

有了加法的启示这里也可以改良一下

for(int i=0; i

(vector)

for(int i=0; i

 3.乘法(高精度a*低精度b)

数组模拟法的难点在于一个公式的理解:

res[i+j]=a[i]*b[j]

 这里我想了一个神奇的例子,希望可以帮助理解:

6*10^{7}=2*10^{2}*3*10^{5}

结果中res[7]=6,乘数中a[2]=2,b[5]=3,从这里我们可以看出res[2+5]=a[2]*b[5],规律立现!

容器法就相对简单一点,直接暴力每一位都乘一遍b,取模作为这一位上的结果,其实和加法类似。

每一位数字=(a[i]*b+jw)%10;

进位+=(a[i]*b+jw)/10;

(数组)

for(int i=0; i

(vector)

vec mul(vec &a,int b)
{
    vec res;
    int t=0;

    for(int i=0; i

4.除法(高精度a÷低精度b)

首先1/31=0,

C++中高精度运算总结_第5张图片

(1*10+2)/31=0,((1*10+2)*10+0)/31=3 ,得到余数27,模拟完过程就可以找到规律了!

每位数字=(上一位的余数*10+本位)/除数

余数=(上一位的余数*10+本位)-除数*结果位数字

 由于除法的力量过于玄学,此处就只放vector版本了。

r=0;//余数要有初始值0
for(int i=a.size()-1; i>=0; i--)//从高位除起,所以后续不需要reverse
{
    r=r*10+a[i];
    res.push_back(r/b);
    r%=b;
}

四.完整代码

篇幅有限,我就不介绍一些细节比如去除前导0了,我会在代码中注释一下。

1.加法

#include 
#include 
#define N 10010
using namespace std;

char a[N],b[N],res[N];
int aa[N],bb[N],rr[N];
int lena,lenb;

int main()
{
    scanf("%s",a);
    scanf("%s",b);

    int lena=strlen(a),lenb=strlen(b);
    int len=max(lena,lenb);

    for(int i=0; i=10)  rr[i+1]++,rr[i]-=10;
    }

    if(rr[len])  len++;//多进一位的情况,比如99+1=100
    
    for(int i=len-1; i>=0; i--)   printf("%d",rr[i]);
}

2.减法

#include 
#include 
#define N 10010
using namespace std;

char a[N],b[N];
int aa[N],bb[N],rr[N];
int lena,lenb;
bool flag=true;

int cmp()//a>b->1   a-1  a==b->0
{
    lena=strlen(a);
    lenb=strlen(b);
    if(lena>lenb)  return 1;
    else if(lenaa-b
    for(int i=0; i=0; i--)  printf("%d",rr[i]);
}

3.乘法

#include 
#include 
#include 

using namespace std;
typedef vector vec;

vec mul(vec &a,int b)
{
    vec res;
    int t=0;

    for(int i=0; i1 && res.back()==0)  res.pop_back();//去除前导0(现在还在0最后面)
    reverse(res.begin(),res.end());

    return res;
}

int main()
{
    string a;
    int b;
    vec aa,rr;
    cin>>a>>b;

    for(int i=a.size()-1; i>=0; i--)  aa.push_back(a[i]-'0');
    rr=mul(aa,b);

    for(int i=0; i

4.除法 

#include 
#include 
#include 

using namespace std;
typedef vector vec;

int r;

vec div(vec &a,int b)
{
    vec res;
    r=0;

    for(int i=a.size()-1; i>=0; i--)//从高位除起,所以后续不需要reverse
    {
        r=r*10+a[i];
        res.push_back(r/b);
        r%=b;
    }

    while(res.size()>1 && res.front()==0)  res.erase(res.begin());//delete 0

    return res;
}

int main()
{
    string a;
    int b;
    vec aa,rr;
    cin>>a>>b;

    for(int i=a.size()-1; i>=0; i--)  aa.push_back(a[i]-'0');
    rr=div(aa,b);

    for(int i=0; i

你可能感兴趣的:(c++,算法)