• 高精度那些事


    高精度加减乘除板子,整理一下成为函数。

    思路

    都是字符串读入,倒序存储。数组(a_0)表示(a)的位数。

    加法

    每一位相加,判断是否需要进位。循环结束后判断最高位是否需要进位,最终调整一下位数。

    减法

    每一位相减,不够减的向前一位借位 (感觉我在学习小学一年级知识??)最后需要调整位数,去掉前导0.

    乘法

    这里和普通的竖式乘法不同。高精乘高精思路为,答案的第i+j-1位,等于两乘数分别的第 i 位和第 j 位相乘。最后需要处理进位和位数的问题。

    除法

    如上图,是地球人用纸和笔做的除法。但是很显然,计算机走试商的方法太麻烦,那就只能把除数移到被除数的最高位(空余的用0补上),再相减,直到剩下的数小于除数(同时记录商),然后进行下一位的计算。

    代码

    加法

    #include<iostream>
    #include"cmath"
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    string in;
    int a[999],b[999],ans[999];
    int strlen(string x){
    	int tot = 0;
    	while(x[tot++] != '');
    	return tot-1;
    }
    void _P(int x[],int y[]){
    	ans[0] = max(x[0],y[0]);
    	for(int i = 1;i <= ans[0]; i++){
    		ans[i] += x[i] + y[i];
    		ans[i+1] += ans[i]/10;
    		ans[i] %= 10;
    	}
    	if(ans[ans[0] + 1]) ans[0] ++;
    } 
    int main(){
    	cin >> in;
    	a[0] = strlen(in);
    	for(int i = 1;i <= a[0]; i++){
    		a[i] = in[a[0] - i] - '0';
    	}
    	cin >> in;
    	b[0] = strlen(in);
    	for(int i = 1;i <= b[0]; i++){
    		b[i] = in[b[0] - i] - '0';
    	}
    	_P(a,b);
    	for(int i = ans[0];i >= 1; i--){
    		cout << ans[i];
    	}
    	cout <<endl;
    }
    

    减法

    注意正负号的检验。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    string in;
    int a[10100],b[10100];
    int c[10100];
    int strlen(string x){
    	int tot = 0;
    	while(x[tot++] != '');
    	tot--;
    	return tot;
    }
    void jian(int x[],int y[]){
    	c[0] = x[0];
    	for(int i = 1;i <= x[0]; i++){ 
    		c[i] += x[i]-y[i];
    		if(c[i] < 0){
    			c[i] += 10;
    			c[i+1]--;
    		}
    	}
    	while(c[0] > 1 && c[c[0]] == 0) c[0]--;
    }
    bool cmp(int x[],int y[]){
    	if(x[0] > y[0]) return 1;
    	if(x[0] < y[0]) return 0;
    	for(int i = y[0];i >= 1; i--){
    		if(x[i] > y[i]) return 1;
    		if(x[i] < y[i]) return 0;
    	}
    	return 1;
    }
    int main(){
    	cin >> in;
    	a[0] = strlen(in);
    	for(int i = 1;i <= a[0]; i++){
    		a[i] = in[a[0] - i] - '0';
    	}
    	cin >> in;
    	b[0] = strlen(in);
    	for(int i = 1;i <= b[0]; i++){
    		b[i] = in[b[0] - i] - '0';
    	}
    	if(!cmp(a,b)){
    		for(int i = 0;i <= max(a[0],b[0]); i++){
    			swap(a[i],b[i]);
    		}
    		cout << '-';
    	}
    	jian(a,b);
    	for(int i = c[0];i >= 1; i--)
    		cout << c[i] ;
    	cout << endl; 
    	return 0;
    }
    

    乘法

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    string in;
    int a[999],b[999],ans[999];
    int strlen(string x){
    	int tot = 0;
    	while(x[tot++] != '');
    	return tot-1;
    }
    void _X(int x[],int y[]){
    	ans[0] = x[0] + y[0]-1;
    	for(int i = 1;i <= x[0]; i++){
    		for(int j = 1;j <= y[0]; j++){
    			ans[j+i-1] += x[i] * y[j];
    			ans[i+j] += ans[j+i-1] / 10;
    			ans[i+j-1] %= 10; 
    		}
    	}
    	if(ans[ans[0]+1] != 0) ans[0]++;
    	while(ans[0] > 1 && ans[ans[0]] == 0) ans[0]--;
    } 
    int main(){
    	cin >> in;
    	a[0] = strlen(in);
    	for(int i = 1;i <= a[0]; i++){
    		a[i] = in[a[0] - i] - '0';
    	}
    	cin >> in;
    	b[0] = strlen(in);
    	for(int i = 1;i <= b[0]; i++){
    		b[i] = in[b[0] - i] - '0';
    	}
    	_X(a,b);
    	for(int i = ans[0];i >= 1; i--){
    		cout << ans[i];
    	}
    	cout <<endl;
    	return 0;
    } 
    

    除法

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    string in;
    int a[10100],b[10100];
    int c[10100];
    int d[10100],r[10100];
    int strlen(string x){
    	int tot = 0;
    	while(x[tot++] != '');
    	tot--;
    	return tot;
    }
    
    void jian(int x[],int y[]){
    	memset(c,0,sizeof c);
    	c[0] = x[0];
    	for(int i = 1;i <= x[0]; i++){ 
    		c[i] += x[i]-y[i];
    		if(c[i] < 0){
    			c[i] += 10;
    			c[i+1]--;
    		}
    	}
    	while(c[0] > 1 && c[c[0]] == 0) c[0]--;
    }
    
    int cmp(int x[],int y[]){
    	if(x[0] > y[0]) return 1;
    	if(x[0] < y[0]) return 0;
    	for(int i = y[0];i >= 1; i--){
    		if(x[i] > y[i]) return 1;
    		if(x[i] < y[i]) return 0;
    	}
    	return 2;
    }
    //商d,余数r
    void chu(int x[],int y[]){
    	memset(d,0,sizeof d);
    	memset(r,0,sizeof r);
    	int tmp[10100] = {};
    	for(int i = 0;i <= x[0]; i++){
    		r[i] = x[i];
    	}
    	d[0] = x[0];
    	for(int i = x[0] - y[0] + 1;i >= 1; i--){
    		memset(tmp,0,sizeof tmp);
    		int cnt = 1;
    		for(int j = i;j <= i + y[0] - 1; j++){
    			tmp[j] = y[cnt++];//移位操作
    		}
    		for(int j = i-1; j >= 1; j--) tmp[j] = 0;
    		tmp[0] = i-1 + y[0];
    		while(cmp(r,tmp)){//比较除数和剩下的被除数
    			d[i]++;
    			jian(r,tmp);
    			memset(r,0,sizeof r);
    			for(int i = 0;i <= max(r[0],c[0]); i++) r[i] = c[i];
    		}
    	}
    	while(d[0] > 1 && d[d[0]] == 0) d[0]--;
    	while(r[0] > 1 && c[c[0]] == 0) r[0]--;
    }
    int main(){
    	cin >> in;
    	a[0] = strlen(in);
    	for(int i = 1;i <= a[0]; i++){
    		a[i] = in[a[0] - i] - '0';
    	}
    	cin >> in;
    	b[0] = strlen(in);
    	for(int i = 1;i <= b[0]; i++)
    		b[i] = in[b[0]-i] - '0'; 
    	
    	chu(a,b);
    	
    	for(int i = d[0];i >= 1; i--) cout << d[i];
    	cout << endl;
    	for(int i = r[0];i >= 1; i--) cout << r[i];
    	cout << endl;
    	return 0;
    }
    

    例题

    回文数

    传送至洛谷 一本通

    特殊的一点就是这里提到的是n进制,所以需要稍微进行一下优化(还好不是乘法除法)

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int a[10086],b[10086];
    int c[10086];
    int n;string in;
    int ans;
    int strlen(string x){
    	int tot = 0;
    	while(x[tot++] != '');
    	return tot-1;
    }
    void pluss(int x[],int y[],int k){//k进制
    	memset(c,0,sizeof c);
    	c[0] = max(x[0],y[0]);
    	for(int i = 1;i <= max(x[0],y[0]); i++){
    		c[i] += x[i] + y[i];
    		if(c[i] >= k){
    			c[i+1] += 1;
    			c[i] %= k;//实际就是把10都改成了k
    		}
    	}
    	if(c[c[0] + 1])
    		c[0]++;
    }
    bool is_hw(int x[]){
    	for(int i = 1;i <= x[0]; i++){
    		if(x[i] != x[x[0] - i + 1]) return 0;
    	}
    	return 1;
    }
    int main(){
    	cin >> n;
    	cin >> in;
    	a[0] = strlen(in);
    	for(int i = 1;i <= a[0]; i++){
    		if(in[a[0] - i] >= '0' && in[a[0] - i] <= '9')
    			a[i] = in[a[0] - i] - '0';
    		else
    			a[i] = 10 + in[a[0]-i] -'A';
    	}
    	for(int i = 0;i <= a[0];i++) c[i] = a[i];
    	while(!is_hw(c)){
    		ans++;
    		b[0] = c[0];
    		a[0] = c[0];
    		for(int i = 1;i <= c[0]; i++){
    			b[i] = c[i];
    			a[i] = c[c[0] + 1 -i];//倒序
    		}
    		pluss(a,b,n);
    		if(ans >= 30){
    			cout << "Impossible" << endl;
    			return 0;
    		}
    	}
    	cout << ans << endl;
    	return 0;
    }
    

    阶乘之和

    洛谷 一本通
    这个真的是我也不知道为什么有点麻烦,之前是打表做的,今天重新写了一下。
    整体如果出问题还是在高精的核心算法上。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int a[10000],b,anss[10000];
    int n;
    int ans[10000],now[10000];
    
    void _x(int x,int y[]){
    	memset(ans,0,sizeof ans);
    	int x0 = 0,k = x;
    	while(k){k /= 10; x0++;}
    	ans[0] = x0 + y[0] -1;
    	for(int i = 1;i <= max(y[0],x0); i++){
    		ans[i] += x * y[i];
    		k = i;
    		while(ans[k] >= 10){
    			ans[k+1] += ans[k] / 10;
    			ans[k] %= 10;
    			k++;
    		}
    		ans[0] = max(k,ans[0]);
    	}
    	while(ans[0] > 1 && ans[ans[0]] == 0) ans[0]--;
    }
    
    void _p(int x[],int y[]){
    	memset(anss,0,sizeof anss);
    	anss[0] = max(a[0],y[0]);
    	for(int i = 1;i <= max(x[0],y[0]); i++){
    		anss[i] += x[i] + y[i];
    		if(anss[i] >= 10){
    			anss[i+1] += anss[i] / 10;
    			anss[i] %= 10; 
    		}
    	} 
    	if(anss[anss[0]+1]){anss[0]++;}
    	for(int i = 0;i <= anss[0]; i++)
    		now[i] = anss[i];
    } 
    int main(){
    	scanf("%d",&n);
    	for(int i = 1;i <= n; i++){
    		a[0] = a[1] = 1;
    		for(int j = 1;j <= i; j++){
    			_x(j,a);
    			for(int i = 0;i <= a[0]; i++) a[i] = ans[i];
    		}
    		_p(ans,now);
    	}
    	for(int i = now[0];i >= 1; i--){
    		cout << now[i];
    	}
    	cout << endl;
    	return 0;
    }
    

    结尾

    其实高精是个上哪里都不会考到的东西,但是这个确实有助于提高代码能力啥的。所以以后还是多写写吧。

  • 相关阅读:
    php configure –help说明
    HTML5(目前)无法帮你实现的五件事多媒体
    Centos搭建PHP5.3.8+Nginx1.0.9+Mysql5.5.17
    lighttpdmod_secdownload 防盗链
    中文环境下PostgreSQL的使用
    一步一步教你安装Nginx+PHP+Mysql
    20+ 个免费和高级的 Web 视频播放器
    二十个你必须知道的SEO概念
    IO流
    sofaBoot
  • 原文地址:https://www.cnblogs.com/Kyriech-Francis/p/Class_gaojing.html
Copyright © 2020-2023  润新知