高精度初步与模拟

1:高精度加法

思路:即小学的简单竖式

一般的累加模板:

#include<bits/stdc++.h>
using namespace std;
string x,y;
int a[100088],b[100088],c[100088];//用a,b数组分别储存两个加数,c储存答案
int  main()
{
	cin>>x>>y;//用string类型读入两个加数
	int A=x.length(),B=y.length();
	for(int i=0;i<A;i++)a[A-i]=x[i]-'0';//将每一位由char转化为int,并对齐,个位是对应序列是1
	for(int i=0;i<B;i++)b[B-i]=y[i]-'0';
	int n=max(A,B);//两个数相加得到的位数一定等于最大的一个数的位数,或者最大一个数的位数加一
	for(int i=1;i<=n;i++){
		c[i]+=(a[i]+b[i]);//每位开始相加,注意一定是累加,因为后一位可能存在向前一位进位的可能
		c[i+1]=c[i]/10;//前面一位一定是零,只需进位,无需累加
		c[i]%=10;//对10取模
	}
	if(c[n+1]==1)n++;//判断是否最高位有进位
	for(int i=n;i>=1;i--)cout<<c[i];//输出时候逆序输出
	return 0;
}

下面是对高精度累加的函数封装(这里函数返回值可用vector或者string,个人比较喜欢string,不大喜欢用vector)

string add(const string& A, const string& B)
{
    string C;
    int t = 0;
    for (int i = A.size()-1, j = B.size()-1; i >= 0 || j >= 0 || t > 0; i--, j--)
    {
        if (i >= 0) t += (A[i] - '0');
        if (j >= 0) t += (B[j] - '0');
        C += ((t % 10) + '0');
        t /= 10;
    }

    reverse(C.begin(), C.end());
    return C;
}

2:高精度减法

 

#include<bits/stdc++.h>
using namespace std;
string a,b;
int m[10088],n[10088],r[10088],flag=0;
int main()
{
	cin>>a>>b;
	if(a<b&&a.length()==b.length()||a.length()<b.length()){//判断哪一个数更大,更大的为被减数
		string temp;//较小的为减数
		temp=a;a=b;b=temp;flag=1;
	}
	int A=a.length(),B=b.length();
	for(int i=0;i<A;i++)m[A-i]=a[i]-'0';//m,A为较大数 
	for(int i=0;i<B;i++)n[B-i]=b[i]-'0';//n,b为较小数
	for(int i=1;i<=A;i++){
		if(m[i]<n[i]){
			m[i+1]-=1;m[i]+=10;//如果被减数这一位不够,向前一位借一
		}
		r[i]=m[i]-n[i];//相减
	}
	while(r[A]==0&&A>1)A--;//去除前导零
	if(flag)cout<<'-';//如果a<b,要加负号
	for(int i=A;i>=1;i--)cout<<r[i];
	return 0;
}

3.高精度乘法

 思路竖式乘法

第i位乘第j位得到第i+j-1位 

设A数的位数a,B的位数为b

最后得到的数的位数为a+b或者a+b-1

时间复杂度(n^2);

#include<bits/stdc++.h>
using namespace std;
int a[2005],b[2005],c[4010];
string x,y;
int main()
{
	cin>>x>>y;
	int A=x.length(),B=y.length();
	for(int i=0;i<A;i++)a[A-i]=x[i]-'0';
	for(int i=0;i<B;i++)b[B-i]=y[i]-'0';
	int C=A+B;
	for(int i=1;i<=A;i++)
	{
		for(int j=1;j<=B;j++)
		{
			c[i+j-1]+=a[i]*b[j];//两者相乘
			c[i+j]+=c[i+j-1]/10;//进位,这里注意一定是累加,可能其他位乘它也会有进位
			c[i+j-1]%=10;//取模
		}
	}
	while(c[C]==0&&C>1)C--;去除前导零
	for(int i=C;i>=1;i--)cout<<c[i];//倒序输出
	return 0;
 } 

4,高精度除法(高精除低精

思路:从高位开始除,如果当前数字没有被除数大,继续向后退

#include<bits/stdc++.h>
using namespace std;
string a;
int n[5005],ans[5005],x=1;
long long b;
int main()
{
	cin>>a>>b;
	int A=a.length();
	for(int i=0;i<A;i++)n[A-i]=a[i]-'0';
	long long t=0;
	if(A==1&&n[1]==0){
		cout<<0;
		return 0;
	}//特判被除数是否为0
	for(int i=A;i>=1;i--){
		t+=n[i];//
		while(t>=b){
			t-=b;
			ans[x]++;//模拟减了几次,这个对应的商的那一位就是几
		}
		x++;//商切换到下一位
		t*=10;//继续除
	}
    x--;//多加了一次位
	int start=1;
	while(ans[start]==0&&start<x)start++;//去除前导0
	for(int i=start;i<=x;i++)cout<<ans[i];
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值