0
点赞
收藏
分享

微信扫一扫

【c++】高精度加法、乘法——加所欲加、乘所欲乘<每日一题>

源码之路 2022-01-23 阅读 104
c++c算法

  前面我写了一篇高精度加法的博客,但那个代码其实是有长度限制的,两个加数最多100位,再高一点就要修改宏定义,很不方便。所以我用c++又写了一遍加法,和乘法。上一篇->博客

这次用的是c++的string。使用很方便,但是写起来有点难理解。

高精加

还是分三步:①倒序输入,对齐个位;②相加,进位;③输出(由于string可以字符串相加,所以不需要倒序输出)。 原理跟上一篇的数组写法差不多。唯一有一点不同就是这次需要判断长短,人后给短的字符串补0,保证俩字符串长度相等,就不多赘述了。

上代码

string add(string str1, string str2, int len)
{
	string ans;
	int ret = 0;
	for (int i = 0; i < len; i++)
	{
		if (ret == 1)
			ret = 1 + str1[len - 1 - i] - '0' + str2[len - 1 - i] - '0';
		else
			ret = str1[len - 1 - i] - '0' + str2[len - 1 - i] - '0';
		int tmp = ret / 10;
		ret = ret % 10;
		ans = char(ret + '0') + ans;
		ret = 0;
		if (tmp != 0)//判断是否需要进位
			ret++;
	}
	if (ret == 1)
		ans = char(1 + '0') + ans;//把int的1转换成字符的1,并加在字符串的前面
	return ans;
}

细节处理好了还是没有什么问题的。

高精乘

这个要考虑的情况就比较多了:

(建议先看代码,再看注解)

①还是方便相乘,我们倒序输入,但是为了节(tou)省(lan),我直接写成了(str1[len1-1-i]-'0')*(str2[len2-1-i]-'0');

②进位,不在只有加1的情况,所以我们要把ret的存起来。然后直接相加

也就是ret+(str1[len1-1-i]-'0')*(str2[len2-1-i]-'0');代码跟上面差不多;

③两数相加,这里我调用了高精加的函数,原因在于:

 ④还有一些特殊情况:比如101*32,101中间的0其实是可以跳过计算的;还有0*32,直接输出0就可以了。

最后说一下乘法的整体思路:模拟竖式乘法,用两组循环对字符串当中的数两两相乘。并将第二次循环得到的字符串保留,调用高精加相加得到最终结果(数据范围可以满足10^2000)

 上代码

string mul(string str1, string str2, int len1,int len2)
{
	if (str1 == "0" || str2 == "0")//判断因数是否有0
		return "0";
	string too;
	string ans;
	ans += "0";
	int ret = 0;//用于进位
	int key = 0;//存储临时变量
	int count = 0;//用于计算too补0的个数,例如第一次不需要补0,第二次补一个......
	for (int i = 0; i < len1; i++)
	{
		step1:
		for (int j = 0; j < len2; j++)
		{
			if (str1[len1 - 1 - i] == '0')
			{
				count++;
				i++;
				goto step1;//跳过数字中间有0(例如101)的情况
			}
			if (ret != 0)//需要进位
			{
				key = ret + (str1[len1 - 1 - i] - '0') * (str2[len2 - 1 - j] - '0');
				ret = 0;
			}
			else
				key = (str1[len1 - 1 - i] - '0') * (str2[len2 - 1 - j] - '0');
			ret = key / 10;//判断是否需要进位
			key = key % 10;
			too = char(key + '0') + too;
		}
		if (ret != 0)
			too = char(ret + '0') + too;
		for (int i = 0; i < count; i++)
			too = too + "0";
		if (count == 0 || ans == "0")
			ans = too;
		else
		{
			int n = too.length() - ans.length();
			while (n)
			{
				ans = "0" + ans;//在ans前补0,保证俩字符串长度相等
				n--;
			}
			ans = add(ans, too, too.length());
		}
		count++;
		ret = 0;
		too = too.erase(0, too.length());//清空too,方便下一次计算。
	}
	return ans;
}

有点繁琐,个人能力有限大家不要介意哈~

我的方法绝对不是最简单的,但是大家可以通过看懂我的代码写出更精简的方案来,我自己也是从这次做题中学到了不少c++的知识,我坚信有一天当我熟练的写高精的时候我的代码一定非常优秀。下面附上我的全部代码,希望与诸君共勉

全部代码

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

string add(string str1, string str2, int len)
{
	string ans;
	int ret = 0;
	for (int i = 0; i < len; i++)
	{
		if (ret == 1)
			ret = 1 + str1[len - 1 - i] - '0' + str2[len - 1 - i] - '0';
		else
			ret = str1[len - 1 - i] - '0' + str2[len - 1 - i] - '0';
		int tmp = ret / 10;
		ret = ret % 10;
		ans = char(ret + '0') + ans;
		ret = 0;
		if (tmp != 0)//判断是否需要进位
			ret++;
	}
	if (ret == 1)
		ans = char(1 + '0') + ans;//把int的1转换成字符的1,并加在字符串的前面
	return ans;
}

string mul(string str1, string str2, int len1,int len2)
{
	if (str1 == "0" || str2 == "0")//判断因数是否有0
		return "0";
	string too;
	string ans;
	ans += "0";
	int ret = 0;//用于进位
	int key = 0;//存储临时变量
	int count = 0;//用于计算too补0的个数,例如第一次不需要补0,第二次补一个......
	for (int i = 0; i < len1; i++)
	{
		step1:
		for (int j = 0; j < len2; j++)
		{
			if (str1[len1 - 1 - i] == '0')
			{
				count++;
				i++;
				goto step1;//跳过数字中间有0(例如101)的情况
			}
			if (ret != 0)//需要进位
			{
				key = ret + (str1[len1 - 1 - i] - '0') * (str2[len2 - 1 - j] - '0');
				ret = 0;
			}
			else
				key = (str1[len1 - 1 - i] - '0') * (str2[len2 - 1 - j] - '0');
			ret = key / 10;//判断是否需要进位
			key = key % 10;
			too = char(key + '0') + too;
		}
		if (ret != 0)
			too = char(ret + '0') + too;
		for (int i = 0; i < count; i++)
			too = too + "0";
		if (count == 0 || ans == "0")
			ans = too;
		else
		{
			int n = too.length() - ans.length();
			while (n)
			{
				ans = "0" + ans;//在ans前补0,保证俩字符串长度相等
				n--;
			}
			ans = add(ans, too, too.length());
		}
		count++;
		ret = 0;
		too = too.erase(0, too.length());//清空too,方便下一次计算。
	}
	return ans;
}

int main()
{
	string str1, str2;
	cin >> str1 >> str2;
	int len1 = (int)str1.length();
	int len2 = (int)str2.length();
	string ans = mul(str1, str2, len1, len2);
	if (len1 > len2)
	{
		for (int i = 0; i < len1 - len2; i++)
			str2 = "0" + str2;
	}
	else if (len1 < len2)
	{
		for (int i = 0; i < len2 - len1; i++)
			str1 = "0" + str1;
	}
	int len = len1 > len2 ? len1 : len2;
	string anst = add(str1, str2, len);
	cout << ans<<endl<<anst;//先输出的是乘法
	return 0;
}
举报

相关推荐

0 条评论