高精度数组加减法(C/C++)

36 阅读3分钟

高精度数组计算(c/c++)

两个高精度数值相加

const int N =  100;
void add(char a[], char b[],char x[], int n1, int n2)
{
	int t = 0;//用来记录当前对应位置相加的结果以及是否进位 
	int i = 0;
	for ( i = 0; i < n1 || i < n2; i++)//遍历两个数值中最大长度次
	{
                //计算当前位置相加结果前先判断当前位置是否有数
		if (i < n1)t += a[i]-'0';
		if (i < n2)t += b[i]-'0';//对应位置相加的结果为
                //【注】a,b数组是char类型,t为int类型,应-'0',即把char转换为int
                
		x[i] =t %10+'0';//(t+a[i]+b[i])%10为结果当前位置应存放的数
                //【注】x数组是char类型,t%10为int类型,应+'0',即把int 转换为char
                
		t /= 10;//如果(t+a[i]+b[i])%10大于等于10应该进位,t/10的结果为1,相反则为0
	}
        //最后t如果为1则在最高位加1,再在最高位之后加\0用来确定结果的长度,用于打印结果
        ///
        提问:为什么是在最高位之后加\0?
        因为在函数之前我们把两个加数前后颠倒比如123456789 + 12 会在进函数前变成98765432121
        因为我们需要从尾部开始计算在记录结果的时候会不停的头插翻转后1如果有进位只需要在尾部加一位所有在
        函数内的结果会是108654321而正确的结果是123456801,与正确结果正好相反所有用\0有后面乱码分割 
        ///
	if (t)
	{
		x[i] = 1 + '0';
		x[i + 1] = '\0';
	}
	else
	{
		x[i] = '\0';
	}
}
int main()
{
	char a[N], b[N], c[N], d[N], x[N];  //通过长字符串记录高精度数值
	scanf("%s %s", a, b);
	int i = 0, la = strlen(a), lb = strlen(b); //记录长度
	for (int i = la - 1, t = 0; i >= 0; i--, t++)c[t] = a[i];//翻转数值,便于在加法时进位
	for (int i = lb - 1, t = 0; i >= 0; i--, t++)d[t] = b[i];
	add(c,d,x,la, lb);
	int n3 = strlen(x);
	//printf("%d", strlen(x));
        //函数返回的值与正确结果相反,所有反向打印就是正确结果
	for (int i = n3-1;i>=0;i--)
	{
		printf("%c", x[i]);
	}
	return 0;
}

由于c比较麻烦所以建议C++

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
vector <int> add(vector <int>& A, vector <int >& B)
{	
	vector <int> C;
	int t = 0;
	for (int i = 0; i < A.size() || i < B.size(); i++)
	{
		if (i < A.size())t += A[i];
		if (i < B.size())t += B[i];
		C.push_back(t % 10);
		t /= 10;
	}
	if (t)C.push_back(t);
	return C;
}
int main()
{
	string a, b;
	cin >> a >> b;
	vector <int>A, B;
	for (int i = a.size() - 1; i >= 0; i--)A.push_back(a[i] - '0');
	for (int i = a.size() - 1; i >= 0; i--)B.push_back(b[i] - '0');
	auto C = add(A, B);
	for (int i = C.size() - 1; i >= 0; i--)printf("%d", C[i]);
}

总体思路是一样的就是利用vector 和string 简化代码过程

两个高精度数相减

#include<iostream>
#include<vector>
#include<algorithm>
bool cmp(vector<int>& A, vector<int>& 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 true;
		}

	}
	return false;
}
vector <int> sub(vector<int>& A, vector<int>& B)
{
	vector<int>C;
	for (int i = 0, t = 0; i < A.size(); i++)
	{
		t = A[i] - t;
		if (i<B.size())t -= B[i];
		C.push_back((t + 10) % 10);//(t + 10) % 10为当前位要保存进结果数组的数
                if (t < 0)t = 1;           //判断是否要像上一位借位
		else t = 0;
	}
	while (C.size() > 1 && C.back() == 0)C.pop_back();//删除前导零比如999-991结果为008所以要删除8前的0,并且如果结果为0要保留一个0;
	return C;
}
int main()
{
	string a, b;
	vector<int>A, B,C;
	cin >> a >> b;
	for (int i = a.size() - 1; i >= 0; i--)C.push_back(a[i] - '0');
	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 (cmp(A, B))
	{
		auto C = sub(A, B);
		for (int i = C.size() - 1; i >= 0; i--)
		{
			printf("%d", C[i]);
		}
	}
	else
	{
		printf("-");
		auto C = sub(B, A);
		for (int i = C.size() - 1; i >= 0; i--)
		{
			printf("%d", C[i]);
		}
	}
	return 0;
}

整体总结:

高精度相加减就是模拟我们日常生活中的竖式计算写代码时应注意进位和借位,以及翻转数组再翻转回来