高精度计算(模板)

高精度计算(10进制)

数据接收和存储

当我们输入的数很长的时候,我们可以采用字符串的形式输入,然后再讲字符串的每一位取出放进数组中

string a;
vector<int> A;//变长数组
cin>>a;
for(int i=a.size()-1;i>=0;i--)A.push_back(a[i]-'0');
//数组第i位存的就是数的第i位

高精度加法

用一个变量t存当前位的和,然后对10取模 多的攒到下一位

#include <iostream>
#include <vector>
using namespace std;
vector<int> add(vector<int> &A,vector<int> &B)
{
    vector<int> c;
    int t=0;
    for(int i=0;i<A.size()||i<B.size();i++)//读每一位
    {
        if(i<A.size())t+=A[i];//如果A有第i位
        if(i<B.size())t+=B[i];//如果B有第i位
        c.push_back(t%10);//就把和结果对10取模放到c
        t/=10;//多出的攒到下一位
        
    }
    if(t)c.push_back(t);//最后一位相加有进位
    return c;
    
}
int main(void)
{
    string a,b;
    cin>>a>>b;
    vector<int> A,B;
    
    for(int i=a.size()-1;i>=0;i--)A.push_back(a[i]-'0');
    for(int i=b.size()-1;i>=0;i--)B.push_back(b[i]-'0');
    
    vector<int> C=add(A,B);
    
    for(int i=C.size()-1;i>=0;i--)cout<<C[i];
    
    return 0;
    
}

高精度减法

这里默认是A大于B所以模板就是A-B,如果B大于A我们要特别判断
所以新增cmp函数思路是 比较长度 长度不相等 长的就是较大的
从高位往低位比较 不同的那一位那个大一点整体就大
上面都不是那就相等

高精度减法:用一个变量t记录借位 然后用A当前位减去借位继续存t中
如果B也有当前位那么t就减去B的当前为t的结果就是当前位运算的结果
t=A[i]-t-B[i];//注意等号右边的t是借位1 然后赋值给等号左边t是暂时存储的变量

该模板试用于前面没有正负号的减法 如果有 需要自己先处理
模板是默认A>B 所以A<B先B-A再加负号
然后(t+10)%10是简写 因为当前位相减结果后t>0 那么就是t 如果t<0 就要向前一位借10
/(t+10) %10就是借后相减结果 如果结果本来大于0了 那么(t+10) %10 没有影响
然后判断 t<0 就是借1位 其他情况不用借 t=0;
打个标记(x+M)%M 以后还会遇到的奥(保持正数 偏移)

#include <iostream>
#include <vector>
using namespace std;
bool cmp(vector<int> &A,vector<int> &B)
{
    if(A.size()!=B.size())return A.size()>B.size();
    for(int i=A.size()-1;i>=0;i--)
       if(A[i]!=B[i])return A[i]>B[i];
    return true;
    
}
vector<int> sub(vector<int> &A,vector<int> &B)
{
    vector<int> c;
    int t=0;
    for(int i=0;i<A.size();i++)//从低位往高位减起!
    {
        t=A[i]-t;
        if(i<B.size())t-=B[i];
        c.push_back((t+10)%10);
        /*
        ------
        如果当前位相减的结果小于零 我们就要往前借一位 原本不够的是复数借位后+10即可
        如果当前为相减结果大于零 说明不需要借位 +10再模10没有影响
        ------
        */
        if(t<0)t=1;//有借位 下一位就减1
        else t=0;//没有借位就不用
        
        
    }
    while(c.size()>1&&c.back()==0)c.pop_back();
    //去掉前导零 比如结果0000 只留下个位0
    return c;
}


int main(void)
{
    string a,b;
    cin>>a>>b;
    vector<int> A,B,C;
    for(int i=a.size()-1;i>=0;i--)A.push_back(a[i]-'0');
    for(int i=b.size()-1;i>=0;i--)B.push_back(b[i]-'0');
    
    if(cmp(A,B)) C=sub(A,B);
    else cout<<'-',C=sub(B,A);
    
    for(int i=C.size()-1;i>=0;i--)cout<<C[i];
    
    
    return 0;
    
}



高精度乘法(模拟乘法竖式运算)

高精乘低精

#include <iostream>
#include <vector>
using namespace std;

//高精度乘法 (这里全部默认自然数(>=0)) 符号问题自己解决
//
vector<int> mul(vector<int> &A, int b) {
	vector<int> c;
	int t = 0;
	for (int i = 0; i < A.size() || t; i++) {
		if (i < A.size())
			t += A[i] * b; //999*99=99*(900+90+9)当前行是当前位上的数与较小数b 相乘结果
		//当前位结果是t%10
		//剩下的进位t/=10;
		//t还有要进位的就进位
		c.push_back(t % 10);
		t /= 10;



	}
	while (c.size() > 1 && c.back() == 0)
		c.pop_back();//乘0的话只留一个零
	return c;



}

int main(void) {
	string a;
	int b;
	cin >> a >> b;
	vector<int> A;
	for (int i = a.size() - 1; i >= 0; i--)
		A.push_back(a[i] - '0');
	auto c = mul(A, b);
	for (int i = c.size() - 1; i >= 0; i--)
		cout << c[i];

	return 0;
}

高精乘高精

参考以下图片
在这里插入图片描述

#include <iostream>
#include <vector>
using namespace std;

vector<int> mul(vector<int> &A,vector<int> &B)
{
    int t=0;
    vector<int> c(A.size()+B.size());//乘法不会超过两个数位相加
    for (int j = 0; j < B.size(); j ++ )
    for (int i = 0; i < A.size(); i ++ )
      c[i+j]+=B[j]*A[i];
     /*  
       这里用乘法交换律换一下顺序好看一点 我写的是模拟A*B的可以写成B*A的
       for (int i = 0; i < A.size(); i ++ )
        for (int j = 0; j < B.size(); j ++ )
            c[i + j] += A[i] * B[j];
    */
    
    
    
    for(int i=0;i<c.size();i++)
    {
        t+=c[i];
        c[i]=t%10;
        t/=10;
    }
    while(c.size()>1&&c.back()==0)c.pop_back();//去掉前导零
    
    
    return c;
    
}
int main(void)
{
    string a,b;
    cin>>a>>b;
    vector<int> A,B;
    
    for(int i=a.size()-1;i>=0;i--)A.push_back(a[i]-'0');
    for(int i=b.size()-1;i>=0;i--)B.push_back(b[i]-'0');
    
    vector<int> c=mul(A,B);
    for(int i=c.size()-1;i>=0;i--)cout<<c[i];
    
    return 0;
    
}


高精除低精

在这里插入图片描述

高精度除法 (这里是模拟/法 整除 向下取整)(正负问题自己解决)
r是余数 然后思路就是 r=当前位+前一位的余数*10为用来除的数 然后r/b就是结果
r%b就是算完后相见的那一步的结果 就是变成下一位的前一位的余数
然后统一 就翻转一下 高位存在后面 然后去掉前导零

#include <bits/stdc++.h>
using namespace std;
vector<int> div_(vector<int> &A,int &b,int &r)
{

    vector<int> c;
     r=0;
    for(int i=A.size()-1;i>=0;i--)
    {
        r=r*10+A[i];
           c.push_back(r/b);
           r%=b;
       //模拟除法 31除以8 3/8不够除 然后第一位结果0 r存的也是0*10+3 然后c放3/8==0
       //然后除完第一位就余3 第二位3*10+1 31/8==3 余7 结束 r就是存除哪一位后的余数 
       //r一开始是0 然后最后就是整个数除完的余数

    }
    reverse(c.begin(),c.end());//让个位存在数组第一位...
       while(c.size()>1&&c.back()==0) c.pop_back();
       //去掉前导零
    return c;

}
int main(void)
{
    string a;
    int b;
    cin>>a>>b;
    vector<int> A;
    int r=0;
    for(int i=a.size()-1;i>=0;i--)A.push_back(a[i]-'0');
    auto c=div_(A,b,r);
    for(int i=c.size()-1;i>=0;i--)cout<<c[i];
    cout<<endl<<r;
    return 0;
}


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值