朴素大数乘法的C++实现

这是模拟竖式乘法的大数乘法的实现,没什么可讲的,代码仅供参考
这里add 函数是大数加法的实现,multiply函数是用二维数组存储乘数各位与被乘数相乘的结果的大数乘法实现,multiplyCompress函数是在上述二维数组中不存储全为0的相乘结果的大数乘法的实现,
multiply2是不使用上述二维数组的大数乘法的实现
C++代码:

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

string charToStr(char be_converted)   
{
	string temp("a");
	if (be_converted != '\0')
		temp[0] = be_converted;
	else
		temp[0] = '0';
	return temp;
}

enum class prefix { left, right, non };
pair<string::size_type, pair<prefix, string::size_type>> alignment(string& left, string& right)
{
	prefix has_prefix_zero;
	string::size_type prefix_zero_length;
	if (left.size() < right.size())
	{
		has_prefix_zero = prefix::left;
		prefix_zero_length = right.size() - left.size();
		left.append(prefix_zero_length, '0');
	}
	else if (left.size() > right.size())
	{
		has_prefix_zero = prefix::right;
		prefix_zero_length = left.size() - right.size();
		right.append(prefix_zero_length, '0');
	}
	else
	{
		has_prefix_zero = prefix::non;

	}
	return { left.size(), {has_prefix_zero, prefix_zero_length} };
}

void deletePrefixZero(const pair<prefix, string::size_type>& has_prefix_zero, string& left, string& right)
{
	if (has_prefix_zero.first == prefix::left)
	{
		left.erase(left.size() - has_prefix_zero.second);
	}
	else if (has_prefix_zero.first == prefix::right)
	{
		right.erase(right.size() - has_prefix_zero.second);
	}
}

string add(string& left, string& right)  //输入倒置,输出倒置
{
	auto r = alignment(left, right);
	string::size_type size = r.first;
	int carry = 0;
	string result;
	for (string::size_type i = 0; i < size; ++i)
	{
		int temp = left[i] - 48 + right[i] - 48 + carry;
		carry = temp / 10;
		result += to_string(temp % 10);
	}
	if (carry != 0)
	{
		result += to_string(carry);
	}
	deletePrefixZero(r.second, left, right);
	return result;

}


string multiply(const string& left, const string& right)  //输入倒置,输出倒置
{
	if (left == "0" || right == "0")
		return "0";
	vector<vector<int>> add_matrix(right.size(), vector<int>(left.size() + 1, 0));
	{
		int carry = 0;
		for (string::size_type i = 0; i < right.size(); ++i)
		{
			carry = 0;
			string::size_type j = 0;
			for (; j < left.size(); ++j)
			{
				int temp = (left[j] - 48) * (right[i] - 48) + carry;
				add_matrix[i][j] = temp % 10;
				carry = temp / 10;
			}
			add_matrix[i][j] = carry;
		}
	}

	string result;
	string carry = "0";
	for (size_t t = 1; t <= left.size() + right.size(); ++t)
	{
		size_t start_group = 0;
		long long start_index = left.size();
		if (t > left.size() + 1)
		{
			start_group = t - left.size() - 1;
		}
		else
		{
			start_index = t - 1;
		}

		string temp = "0";
		while (start_group < right.size() && start_index >= 0)
		{
			string str_form = to_string(add_matrix[start_group][start_index]);
			if (str_form != "0")
				temp = add(temp, str_form);
			++start_group;
			--start_index;
		}

		if (carry != "0")
			temp = add(temp, carry);
		result += charToStr(temp[0]);
		carry = temp.substr(1, temp.size() - 1);
		if (carry == "")
			carry = "0";
	}

	if (result[result.size() - 1] == '0')
	{
		return result.substr(0, result.size() - 1);
	}
	else
	{
		return result;
	}
}

string multiplyCompress(const string& left, const string& right)  //输入倒置,输出倒置,压缩存储版本
{
	if (left == "0" || right == "0")
		return "0";
	vector<vector<int>> add_matrix;
	vector<bool> is_zero_group(right.size());
	vector<int> before_non_zero_zero_num;
	{
		int continuous_zero = 0;
		int carry = 0;
		for (string::size_type i = 0; i < right.size(); ++i)
		{
			if (right[i] == '0')
			{
				is_zero_group[i] = true;
				++continuous_zero;
				continue;
			}
			is_zero_group[i] = false;
			before_non_zero_zero_num.push_back(continuous_zero);
			continuous_zero = 0;
			add_matrix.push_back(vector<int>(left.size() + 1));
			carry = 0;
			string::size_type j = 0;
			for (; j < left.size(); ++j)
			{
				int temp = (left[j] - 48) * (right[i] - 48) + carry;
				add_matrix.back()[j] = temp % 10;
				carry = temp / 10;
			}
			add_matrix.back()[j] = carry;
		}
	}

	size_t next_visit_non_zero;
	int cur_before_zero_num;
	if (is_zero_group[0])
	{
		next_visit_non_zero = 0;
		cur_before_zero_num = 1;
	}
	else
	{
		next_visit_non_zero = 1;
		cur_before_zero_num = 0;
	}
	string result;
	string carry = "0";
	for (size_t t = 1; t <= left.size() + right.size(); ++t)
	{
		size_t start_group = 0;
		long long start_index = left.size();
		if (t > left.size() + 1)
		{
			start_group = t - left.size() - 1;
		}
		else
		{
			start_index = t - 1;
		}

		string temp = "0";

		if (start_group == 0)
		{
			start_index -= before_non_zero_zero_num[0];
		}
		else
		{
			if (is_zero_group[start_group])
			{
				start_group = next_visit_non_zero;
				start_index -= before_non_zero_zero_num[next_visit_non_zero] - cur_before_zero_num;
				++cur_before_zero_num;
			}
			else
			{
				start_group = next_visit_non_zero;
				cur_before_zero_num = 0;
				++next_visit_non_zero;
			}
		}
		while (start_group < before_non_zero_zero_num.size() && start_index >= 0)
		{
			string str_form = to_string(add_matrix[start_group][start_index]);
			if (str_form != "0")
				temp = add(temp, str_form);
			++start_group;
			if (start_group != before_non_zero_zero_num.size())
			{
				start_index -= before_non_zero_zero_num[start_group] + 1;
			}
		}

		if (carry != "0")
			temp = add(temp, carry);
		result += charToStr(temp[0]);
		carry = temp.substr(1, temp.size() - 1);
		if (carry == "")
			carry = "0";
	}

	if (result[result.size() - 1] == '0')
	{
		return result.substr(0, result.size() - 1);
	}
	else
	{
		return result;
	}
}

string multiply2(const string& left, const string& right)
{
	if (left == "0" || right == "0")
		return "0";
	string result;
	string carry = "0";
	for (size_t t = 1; t <= left.size() + right.size() - 1; ++t)
	{
		size_t start_group = 0;
		long long start_index = left.size() - 1;
		if (t > left.size())
		{
			start_group = t - left.size();
		}
		else
		{
			start_index = t - 1;
		}

		string temp = "0";
		while (start_group < right.size() && start_index >= 0)
		{
			string med = to_string(static_cast<long long>((right[start_group] - 48) * (left[start_index] - 48)));
			reverse(med.begin(), med.end());
			if (med != "0")
				temp = add(temp, med);
			++start_group;
			--start_index;
		}

		if (carry != "0")
			temp = add(temp, carry);
		result += charToStr(temp[0]);
		carry = temp.substr(1, temp.size() - 1);
		if (carry == "")
			carry = "0";
	}
	result.append(carry);

	if (result[result.size() - 1] == '0')
	{
		return result.substr(0, result.size() - 1);
	}
	else
	{
		return result;
	}
}

int main()
{
	string left = "123";
	string right = "456";

	reverse(left.begin(), left.end());
	reverse(right.begin(), right.end());

	string result = multiply(left, right);
	reverse(result.begin(), result.end());
	cout << "multiply:";
	cout << result << endl;

	string result2 = multiply2(left, right);
	cout << "multiply2:";
	reverse(result2.begin(), result2.end());
	cout << result2 << endl;

	/*string result3 = doKaratsubaMultiply(left, right, true);
	cout << "Karatsuba:";
	reverse(result3.begin(), result3.end());
	cout << result3 << endl;*/

	string result4 = multiplyCompress(left, right);
	cout << "Compress:";
	reverse(result4.begin(), result4.end());
	cout << result4 << endl;

	for (int i = 0; i <= 10000; ++i)
	{
		for (int j = 1000; j <= 1100; ++j)
		{
			string left = to_string(i);
			string right = to_string(j);
			reverse(left.begin(), left.end());
			reverse(right.begin(), right.end());

			cout << i << "*" << j << endl;
			string m_r = multiply(right, left);
			reverse(m_r.begin(), m_r.end());
			cout << "multiply:";
			cout << m_r << endl;

			string m_r2 = multiplyCompress(right, left);
			cout << "Compress:";
			reverse(m_r2.begin(), m_r2.end());
			cout << m_r2 << endl;
			if (m_r == m_r2)
			{
				cout << "运算结果正确" << endl;
			}
			else
			{
				cout << "ERROR:运算结果错误!" << endl;
				exit(-1);
			}
			cout << endl;
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值