高精四则运算整数

本文详细介绍了高精度整数运算,包括高精加法(倒序相加)、高精减法(大小判断+倒序相减)、高精乘法(倒序相乘+等级处理)以及模拟除法的实现过程,适合深入理解整数运算技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

高精四则(整数)

注:高精整数运算,这一篇就够了

一、高精加法——倒序相加

1.1、高精加高精
1.1.1思路方法:

   倒序,将末端的个位数经依次完全调序后,即为首位,自此,从左向右为低位到高位,依次相加并处理进位即可。

核心:低位相加向高位,记得处理1进位:。 因为两个各位数相加不会超过20,所以最多进位为1

// 这部分是伪代码,不能跑!不能跑!!
vector<int> C(size, 0);//初始化,size大小未知
k = 0 // k为进位值,有进位为1,否则为0
// 外层循环处理,至结束
{
  C[i] = A[i] + B[i] + k;//A、B为处理后的、倒序的加数
  k = C[i] / 10;
  C[i] %= 10; // C[i]存答案的第i位
}

  有两种方法,一种是静态的、顺序数组存储方式,另一种为动态的、大小可变的vector数组,两者在细节上略有不同。
  对于vector整型数组A而言,假如A中有n个数据,那么只能访问A[0]和A[n-1],对于下一个或者更靠后的位置比如A[n],是不能对其直接操作的,可以理解为动态数组目前开到了A[n-1],对于下一个数据下还没分配内存,这样直接赋值:A[n] = 5,这不行!想要增加一个值为5的元素,这样写即可:A.push_back(5)。这里完成了vector数组的初始化:vector C(size, 0);,使得即便没有C.push_back(value) size次,也可以访问C[0]~C[size-1]之间的元素。

1.1.2具体实现
  1. “静态数组”:大小不可改变,支持的位数由数组大小决定。

    #include <iostream>
    #include <cstring>
    
    using namespace std;
    
    const int MAXLEN = 2010;//最多为2010位的大数
    
    char t[MAXLEN];
    char a[MAXLEN], b[MAXLEN];
    
    int main()
    {
    	cin >> t;//输入第一个数,并倒序
    	for (int i = strlen(t)-1, j = 0; i >= 0; -- i)  a[j ++] = t[i] - '0';
    	
    	cin >> t;//输入第二个数,并倒序
    	for (int i = strlen(t)-1, j = 0; i >= 0; -- i)  b[j ++] = t[i] - '0';
    	
    	for (int i = 0, k = 0; i < MAXLEN; ++ i)
    	{
    		a[i] += b[i] + k;
    		k = a[i] / 10;
    		a[i] %= 10;
    	}
    	//准备输出 
    	int i = MAXLEN - 1;
    	while (i >= 0 && !a[i]) -- i;//出去前导零
    	//如果存在输入数字0加0,则需要特判除去前导零后,是否有数,但一般不会出现这种情况 
    	while (i >= 0) cout << (int)a[i --];//依次输出高位到低位 
    	
    	return 0; 
    } 
    
  2. vector数组:大小可变、灵活,基本无限制(内存够用的前提下)。

    #include <iostream>
    #include <string>
    #include <vector>
    
    using namespace std;
    
    //这样typedef后下面的VI可替换为vector<int>
    typedef vector<int> VI;
    
    VI Add(VI& A, VI& B)
    {
    	VI C;// 存答案
    	int i = 0, k = 0;
    	//先处理A和B的等长部分 
    	while (i < A.size() && i < B.size())
    	{
    		k += A[i] + B[i];
    		C.push_back(k % 10);
    		k /= 10; ++ i;
    	}
    	//如果B每一位都加完了,A还有剩余,则将A剩余部分加到C中 
    	while (i < A.size())
    	{
    		k += A[i];
    		C.push_back(k % 10);
    		k /= 10; ++ i;
    	}
    	//如果A每一位都加完了,B还有剩余,则将B剩余部分加到C中 
    	while (i < B.size())
    	{
    		k += B[i];
    		C.push_back(k % 10);
    		k /= 10; ++ i;
    	}
    	
    	return C;
    }
    
    int main()
    {
    	string a, b;
    	VI A, B, C;//A和B为存待操作数,C为结果
    	
    	cin >> 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');
    	
    	C = Add(A, B); 
    	
    	for (int i = C.size()- 1; i >= 0; -- i) cout << C[i];
    	
    	return 0;
    } 
    
1.2、高精加低精
1.2.1思路方法

    与高精+高精类似,就是把其中一个改为低精度,对于低精度,同样的,为了每次获取其位置上的数,只需要每次对低精数处理即可。

核心:处理低精数

// 外层循环...两个条件
//1.A数组加完了 2.b加完了
{
 k += A[i] + b % 10;
 C.oush_back(k % 10);
 k /= 10, b /= 10;
}

 后续针对1,2两种情况处理,

  1. 如果A数组加完了,判断b是否为0,如果不为0,需要把b的每一位放入答案数组C中,即:

    while (b) 
    {
        C.push_back(b % 10);
        b /= 10;
    }
    
  2. 如果b加完了,判断A有没有加完,如果A有剩余,将A剩余每一位加入答案数组C中,即:

    while (i < A.size())
    {
        k += A[i];
        C.push_back(k % 10);
        k /= 10; ++ i;
    }
    
1.2.2具体实现
#include <iostream>
#include <vector>

using namespace std;

typedef vector<int> VI;

VI Add(VI& A, int b)
{
	VI C;//因为后面用的是push_back()的方式,没有初始化
	
	int i = 0, k = 0;
	
	while (i < A.size() && b != 0)
	{
		k += A[i] + b % 10;
		C.push_back(k % 10);
		k /= 10, b /= 10; ++ i;
	}
	while (i < A.size())
	{
		k += A[i];
		C.push_back(k % 10);
		k /= 10; ++ i;
	}
	while (b != 0) 
	{
		k += b % 10;
		C.push_back(k % 10);
		k /= 10, b /= 10; ++ i;
	}
	
	return C;
}

int main()
{
	VI A, C; 
	string a; int b;
	
	cin >> a >> b;
	
	for (int i = a.size()-1; i >= 0; -- i) A.push_back(a[i] - '0');
	
	C = Add(A, b); 
	
	for (int i = C.size()-1; i >= 0; -- i) cout << C[i];
	
	return 0;
}

二、高精减法——大小判断+倒序相减

2.1思路方法

先判断大小,始终用大减小的方式来计算。对于A - B,
A − B = { A − B ;   A   ≥   B − ( B − A ) ;   A < B A - B = \left\{ \begin{aligned} & A - B; \ A \ {\geq} \ B \\ & - (B - A); \ A < B \end{aligned} \right. AB={AB; A  B(BA); A<B

核心:大减小,不够则借位,下一位需要减去这个借位

规则:低位借一算十,即低位加十,相邻高位减一

注意对前导0的处理,前导的出现是由于两数最高位数字大小相同造成的,如果最高位减为0则不应该输出,除去前导零:while (C.size() > 1 && C.back() == 0) C.pop_back();

2.2具体实现
#include <iostream>
#include <vector>

using namespace std;

typedef vector<int> VI;

bool compare(VI& A, VI& 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;
}

VI sub(VI& A, VI& B)
{
	VI C(A.size(), 0);
	int i = 0, k = 1;
	while (i < B.size())
	{
		C[i] = A[i] - B[i] - !k;
		k = (C[i] + 10) / 10;
		C[i] = (C[i] + 10) % 10;
		++ i;
	}
	while (i < A.size())
	{
		C[i] = A[i] - !k;
		k = (C[i] + 10) / 10;
		C[i] = (C[i] + 10) % 10;
		++ i;
	}
	while (C.size() > 1 && C.back() == 0) C.pop_back();
	
	return C;
}

int main()
{
	VI A, B, C;
	string a, b;
	
	cin >> 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');
	
	if (compare(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;
} 

三、高精乘法——倒序相乘+等级处理

3.1、高精乘高精
3.1.1思路方法:

将两个数倒序,呈由低位到高位排列。

核心:等级处理

个位 * 个位 = 个位

个位 * 十位 = 十位

十位 * 个位 = 十位

A数组从低位到高位A[0]~A[n]

B数组从低位到高位B[0]~B[m]

对于A数组的第i位,乘以B数组的第j位,得到答案数组C的第i+j位

(如果感觉不对,请注意下标从0开始存储的)

3.1.2具体实现
#include <iostream>
#include <vector>

using namespace std;

typedef vector<int> VI;

VI mul(VI& A, VI& B)
{
	VI C(A.size()+B.size(), 0);
	
	for (int i = 0; i < A.size(); ++ i)
	   for (int j = 0; j < B.size(); ++ j)
	       C[i+j] += A[i] * B[j];
	int k = 0;
	for (int i = 0; i < C.size(); ++ i)
	{
		C[i] += k;
		k = C[i] / 10;
		C[i] %= 10;
	}
	while (C.size() > 1 && C.back() == 0) C.pop_back();
	
	return C;
}

int main()
{
	VI A, B, C;
	string a, b;
	
	cin >> 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');
	
	C = mul(A, B);
	
	for (int i = C.size()-1; i >= 0; -- i) cout << C[i];
	
	return 0;
}
3.2、高精乘低精
3.2.1思路方法

与上面高精乘高精大致相同,但是细节不同。

核心:等级处理

  大数倒序存于A数组中,A[0]~A[n-1]分别代表个位、十位、百位… 将A[0] ~ A[n-1]每个数乘以低精乘数b,代表有b个个位数、b个十位数、b个百位数…将结果存于答案数组C中,后续处理C。

  证明这一做法的科学性: abcd,这个四位数,乘以G,假设结果为ans,那么ans = abcd * G。且abcd = a + 10b+100c+1000d,ans = a * G + 10b * G + 100c * G + 1000 * G,相当于每一位数乘以G,并且其等级不变,即:a (个位)* G + b(十位)*G + c(百位) *G + d千位() *G

3.2.2具体实现

#include <iostream>
#include <vector>

using namespace std;

typedef vector<int> VI;

VI mul(VI& A, int b)
{
	VI C(A.size(), 0);
	int k = 0;
	for (int i = 0; i < A.size(); ++ i)
	{
		C[i] = A[i] * b + k;
		k = C[i] / 10;
		C[i] %= 10;
	}
	while (k)
	{
		C.push_back(k % 10);
		k /= 10;
	}
	while (C.size() > 1 && C.back() == 0) C.pop_back();
	
	return C;
}

int main()
{
	VI A, C;
	string a; int b;
	
	cin >> a >> b;
	
	for (int i = a.size()-1; i >= 0; -- i) A.push_back(a[i]-'0');
	
	C = mul(A, b);
	
	for (int i = C.size()-1; i >= 0; -- i) cout << C[i];
	
	return 0;
}

四、高精除法——模拟除法式

4.1思路方法

按照除法算式的思路,从高位到低位算,恰好不需要倒序。

核心:模拟除法式

(高位数 + 10*余数) / 除数 = 商(该位置答案值) …余数(下一位用)

最后剩下的的余数即为这个总式的余数

4.2具体实现
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

typedef vector<int> VI;

VI div(VI& A, int b, int& r)
{
	VI C(A.size(), 0);
	for (int i = 0; i < A.size(); ++ i)
	{
		r = A[i] + r * 10;
		C[i] = r / b;
		r %= b;
	}
	reverse(C.begin(), C.end());
	while (C.size() > 1 && C.back() == 0) C.pop_back();
	
	return C;
}

int main()
{
	VI A, C;
	string a; int b, r = 0;//r最后为余数 
	
	cin >> a >> b;
	
	for (int i = 0; i < a.size(); ++ i) A.push_back(a[i]-'0');
	
	C = div(A, b, r);
	
	for (int i = C.size()-1; i >= 0; -- i) cout << C[i];
	
	return 0;	
}

THEEND…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值