高精度问题详解

高精度

运算:加法、减法、阶乘、乘法

翻转:

这些运算都是从小位开始,所以一般需要翻转。以字符串储存:reverse(a.begin(),a,end())。以数组储存:

for (int i1 = lena1 - 1; i1 >= 0; i1--) {
			a1[lena1-1-i1] = a[i1] - '0';
		}
进位、借位:

加法、减法:

for(int k=0;k<ll+1;k++){//进位运算 
			if(ans[k]>'9'){
				ans[k]-=10;
				ans[k+1]++;
			}
		}
		for(int k=0;k<ll;k++){//借位运算 
			if(ans[k]<'0'){
				ans[k]+=10;
//				cout<<ans[k];
				ans[k+1]--;
			}
		}

乘法:

if(a[i]>=10)
                {
                    a[i+1]+=a[i]/10;
                    a[i]%=10;
                }
                a[i]*=N;

具体题目:

P1120 大整数加法

题目描述

给出两个 200 位以内的正整数,求其和。

输入描述

多组测试数据。每组测试数据包括两行,每行一个数。

输出描述

每组测试输出一行,为所求两个整数之和。

样例输入

123

456

样例输出

579

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;

int main(){
	string a,b;
	while(cin>>a>>b){
		string ans;
		int aa = a.length();//字符串a长度 
		int bb = b.length();//字符串b长度 
		int ss = min(aa,bb);//最小长度 
		int ll = max(aa,bb);//最大长度 
		reverse(a.begin(), a.end());//将字符串翻转用于从小位开始计算 
		reverse(b.begin(), b.end());

		for(int i=0;i<ss;i++)
			ans+= a[i]+b[i]-'0';//相同位数之间计算 
		if(aa>bb)//将大位数单独加在字符串尾部 
			{
				for(int j=ss;j<aa;j++)
					ans+= a[j];}//将 
		else if(bb>aa)
			for (int j=ss;j<bb;j++)
				ans+= b[j];
		ans+='0';//用于最大位进位 
		for(int k=0;k<ll+1;k++){//进位运算 
			if(ans[k]>'9'){
				ans[k]-=10;
				ans[k+1]++;
			}
		}
		reverse(ans.begin(),ans.end());//翻转为正常顺序 
		for(int i=ans.find_first_not_of('0');i<ll+1;i++){//找到第一位不为0的位置,一次输出 
			if(i==-1){
				cout<<0;
				return 0;
			}
			cout<<ans[i]-48;
		}
		cout<<endl;
	}
	return 0; 
	
}
P1121 大整数减法

题目描述

给出两个 200 位以内的正数,算出第一个数减第二个数的值(结果为正)。

输入描述

每组测试数据包括两行,第一行为被减数,第二行为减数。

输出描述

每组测试数据输出一行,为所求两个整数之差。

样例输入

987

654

样例输出

333

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;

int main(){
	string a,b,temp;
	int flag = 0;
	while(cin>>a){
		cin>>b;
		string ans;
		int aa = a.length();//字符串a长度 
		int bb = b.length();//字符串b长度 
		int ss = min(aa,bb);//最小长度 
		int ll = max(aa,bb);//最大长度 
		reverse(a.begin(), a.end());//将字符串翻转用于从小位开始计算 
		reverse(b.begin(), b.end());
		if(aa==bb){
			if(b>a){
				temp = a;
				a = b;
				b = temp;
				flag = 1;		
			}
		}
		else if(bb>aa){
			temp = a;
			a = b;
			b = temp;
			aa = bb;
			flag = 1;	
		} 
		for(int i=0;i<ss;i++)
			ans+= a[i]-b[i]+'0';//相同位数之间计算 
		for(int j=ss;j<ll;j++)
			ans+= a[j];
		for(int k=0;k<ll;k++){//借位运算 
			if(ans[k]<'0'){
				ans[k]+=10;
//				cout<<ans[k];
				ans[k+1]--;
			}
		}
		reverse(ans.begin(),ans.end());//翻转为正常顺序 
		if(flag) cout<<'-';
		for(int i=ans.find_first_not_of('0');i<ll;i++){//找到第一位不为0的位置,一次输出 
		
		cout<<ans[i]-48;
		}
		cout<<endl;
	}
	return 0; 
	
}
P1134 高精度阶乘

题目描述

求一个非负整数 N 的阶乘的精确值(N 的大小保证 N 的阶乘不超过 3000 位)。

输入描述

有多组测试数据,每组测试数据包含一行非负整数 N。

输出描述

对于每组测试数据,输出一行答案。

样例输入

3

10

50

样例输出

6

3628800

30414093201713378043612608166064768844377641568960512000000000000

#include<bits/stdc++.h>
using namespace std;
//对每一位进行数字乘法,处理好进位 
int main()
{
    int N;
    while(cin>>N)
    {
        int a[3001]={0};
        int i=0;
        a[0]=1;
        while(N)
        {
            for(i=0;i<3001;i++)
            {
                if(a[i]>=10)
                {
                    a[i+1]+=a[i]/10;
                    a[i]%=10;
                }
                a[i]*=N;
            }
            N--;
        }
        while(a[i]==0)
        {
            i--;
        }
        for(;i>=0;i--)
            cout<<a[i];
        cout<<endl;
    }
    return 0;
}
P1136 高精度乘法

题目描述

给出两个长度小于 100 位的正整数,求其乘积。

输入描述

两行,一行一个数。

输出描述

一行,为所求乘积。

样例输入

1937

2931

样例输出

5677347

#include<iostream> 
#include<cstring>
using namespace std;
//将字符串每一位改为数字,再反向计算,最后处理进位问题。 
int main() {
	char a[101], b[101];       //定义字符数组是为了好测量,输入的长度
	while (cin >> a >> b) {
		char swap[101];         //用来进行交换的,超过a的长度小于b的长度
		int a1[101] = { 0 }, b1[101] = { 0 };  //接受a与b的,并将其转化为整形数组和反转
		int lena1, lenb1;      //测量a与b的长度
		lena1 = strlen(a), lenb1 = strlen(b);
		int n;                 //接受lena1与lena2的最大值,并且为下面的动态数组做准备
		n = (lena1 > lenb1 ? lena1 : lenb1);
		//申请动态数组,a与b的乘积最多有2*n位数
		int *p;
		p = new int[2 * n];
		//将p数组清零
		memset(p, 0, sizeof(int)*(2 * n));
		//控制b1为最短的数组
		if (lena1 < lenb1) {
			strcpy(swap, b);
			strcpy(b, a);
			strcpy(a, swap);
		}
		lena1 = strlen(a), lenb1 = strlen(b);
		//反转a数组
		for (int i1 = lena1 - 1; i1 >= 0; i1--) {
			a1[lena1-1-i1] = a[i1] - '0';
		}
		//反转数组b
		for (int k1 = lenb1 - 1; k1 >= 0; k1--) {
			b1[lenb1 - 1 - k1] = b[k1] - '0';
		}
		int len;    //控制p数组从第几位开始
		for (int i = 0; i < lenb1; i++) { 
			len = i;
			for (int k = 0; k < lena1; k++) {
				p[len] += b1[i] * a1[k];
				if (p[len] > 9) {
					p[len + 1] += p[len] / 10;
					p[len] = p[len] % 10;
				}
				len++;
			}
		}
		while (p[len] == 0) {
			len--;
		}
		for (int k2 = len ; k2 >= 0; k2--) {
			cout << p[k2];
		}
		delete[]p;
		cout << endl;
	}
	return 0;
}
posted @ 2022-05-18 16:44  chanxe  阅读(31)  评论(0编辑  收藏  举报