高精度运算模板(c\c++)

         前言

         由于long long类型也会有上限,所以引入了高精度的概念,其实就是把其当成字符串放入数组进行处理。【已经通过测试】

关于高精度加减乘法:

         注意对位细节,跟平常的加减乘除一样,从最后往前进行相加,然后保存超出10的部分。所以我们需要创数组把我们输入的字符串从后往前进行遍历.直接上代码

#include <iostream>
using namespace std;
#include <string>
#include <cstring>
#define N 105000
int a[N], b[N], c[N];
string ss1, ss2;
int main(void)
{
    cin >> ss1 >> ss2;
	memset(a, 0, sizeof(a));//数组清零
	memset(b, 0, sizeof(a));
	memset(c, 0, sizeof(a));
	int sz1 = ss1.size(), sz2 = ss2.size();
	for (int i(0); i < sz1; i++)a[sz1 - i] = ss1[i] - '0';  //相当于逆换。
	for (int i(0); i < sz2; i++)b[sz2 - i] = ss2[i] - '0';
     ......
     return 0;
}

 这就是交换后的结果.-------->除法跟加减乘不一样(待会在解释)[加减乘都是这模板可以直接套]

1.高精度加法(最简单)

直接对位相加,当某位超过10直接%10-->然后下一位直接对加相应多出的数即可
 

	for(int i(1);i<cz;i++)//cz的长度为max(sz1,sz2)+1;
{
		c[i]=n1[i]+n2[i]+x;    
		x=c[i]/10;                   //其实这里也可以加一个条件 当..x>=10时才执行
		c[i]%=10;                    //%10保存<10的数
}
		c[i]=x;//保存最后的进位;

2.高精度减法

减法会比加法多一个判定条件 ----->  当输入的ss1<ss2时 我们交换一下  这样就会保持 ss1>=ss2 因为相减为 负数后面比较麻烦处理  我们 直接先判断 率先加一个负号 即可.

先上判定代码:
 

	//先判断ss1是否比ss2小,如果小就交换两则的顺序
	if ((ss1.size()<ss2.size()) || (ss1.size() ==ss2.size() && ss1<ss2)) {
		swap(ss1, ss2);   //交换
		cout << "-";
	}//并率先输出一个负号} 

模板:
 

int max_c = max(sz1, sz2);    //这里与加法不同没有+1,因为减法不存在最后多一位的情况
	for (int i(1); i <= max_c; i++) {
		if (a[i] < b[i]) {
			a[i + 1] --;                        //如果a<b我们直接向下一位借位,然后本位加10.
			a[i] += 10;}
		c[i] = a[i] - b[i];
	}

3.高精度乘法

自己在本子上列一下:

 

图片来源:B站-(自己难得写,直接搬运一下别人的 )

麦克老师讲算法

看对应关系,直接上代码:(因为对应相加 又因为采取二重循环,所有c下标对应关系为:i+j-1(i=j=1开始)-------<>

	for (int i = 1; i <= sz1; i++) {
		for (int j=1; j <= sz2; j++) {
			c[i + j - 1] += a[i] * b[j];                  //看不懂,可以直接记模板
			c[i + j] += c[i + j - 1] / 10;
			c[i + j - 1] %= 10;
		}
	}

4.高精度除法

             4.1(高精度/低精度)

基本运算大体一致,只是直接按照顺序存储不再用逆置.

先上代码:
算了 还是找了点对应资料 ............................................................................................................

图片来源:B站-

麦克老师讲算法

模板:

for(int i(0);i<=sz;i++){         //sz为输入高精度数的长度
   b[i]=(x*10+a[i])/10;
   x=(x*10+a[i])%10;
}

输出格式(注意0000!!!!!!!)
 

while(b[max_c] == 0 && max_c <la)max_c++;   //max_c=1
                                            
	for (int i = max_c; i <=la; i++)
		cout << b[i];
	cout << endl;

4.高精度/高精度

不好解释,直接看代码(模板也不好写hahha)----><------
 

#include <iostream>
#include <cstring>
#include <string>
using namespace std;
#define N 100005
string ss1, ss2;
int a[N], b[N], c[N],temp[N];  //保存字符数组内容;

void temp_create(int temp[], int b[], int n) {
	int i = 1;
	for (i;i<=b[0]; i++) {
		temp[n + i - 1] = b[i];
	}
		temp[0] = n+b[0]-1;//
}
int cmp(int a[], int temp[]) {
	if (a[0] > temp[0])return 1;
	if (a[0] < temp[0])return -1;
	for (int i(a[0]); i > 0; i--) {
		if (a[i] > temp[i])return 1;
		if (a[i] < temp[i])return -1;
	}
	return 0;
	
}
void start_sub(int a[], int temp[]) {
	int max_sub = max(a[0], temp[0]);
	for (int i(1); i <= max_sub; i++) {
		if (a[i] < temp[i]) {
			a[i] += 10;
			a[i + 1]--;
		}
		a[i] = a[i] - temp[i];
	}
	//删除前缀0;
	while (a[a[0]]==0&&a[0]>0)a[0]--;
	
}
void print(int num[]) {
	if (num[0] == 0) {
		cout << 0;
		return;
	}
	for (int i(num[0]); i > 0; i--) {
		cout << num[i];
	}

	return;
}
int main(void)
{
	cin >> ss1 >> ss2;  //首先输入除数和被除数放入字符数组
	memset(a, 0, sizeof(a));
	memset(b, 0, sizeof(b));
	memset(c, 0, sizeof(c));
	a[0] = ss1.size(), b[0] = ss2.size();  //判定大小放入首地址
	c[0] = a[0] - b[0] + 1;//按照规律可得输出的大小最大为s1长-s2长+1;
	for (int i(0); i < a[0]; i++) a[a[0] - i] = ss1[i] - '0';
	for (int i(0); i < b[0]; i++) b[b[0] - i] = ss2[i] - '0';
	for (int i(c[0]); i > 0; i--) {
		memset(temp, 0, sizeof(temp));              //每次执行清空一次
		temp_create(temp,b,i );
		while (cmp(a, temp) >= 0) {
			c[i]++;                          //对应位数进行++
			start_sub(a, temp);             //进行高精度减法
		}
	}
	while (c[c[0]] == 0 && c[0] > 0)c[0]--; //删除前缀0
	print(c);//输出结果
	cout << " ";
	print(a);//输出余数
	return 0;
}

5.输出部分

一定记得消除多余0!
(这里适合:加减乘 ,除法在上面)

while(c[max_c] == 0 && max_c > 1)max_c--;   //max_c长度看情况而定
                                            //加减直接对应i 而乘法对应 sz1+sz2(ss1\ss2总长)
	for (int i = max_c; i > 0; i--)
		cout << c[i];
	cout << endl;

总结 :除了高精度除 其余的都还是很好掌握,多看两遍自己打出来就基本会了.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值