这是模拟竖式乘法的大数乘法的实现,没什么可讲的,代码仅供参考
这里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;
}
}
}