如何对字符向量执行大整数乘法

How to perform BigInteger multiplication on char vectors?

本文关键字:整数 执行 向量 字符      更新时间:2023-10-16

我正在 c++ 中实现一个 BigInt,并试图重载乘法运算符。我正在将大整数存储在字符向量中。

vector<char> storage;

这是我为实现运算符*(int(所做的

BigInt BigInt::operator*(int x)
{
int extra = 0;
int dec_mod = pow(10, this->storage.size());
for (auto & g : storage) {
    g = g * x + extra;
    int mod_g = g % dec_mod;
    extra = g / dec_mod;
    g = mod_g;
}
while (extra > 0) {
    storage.push_back(extra % dec_mod);
    extra /= dec_mod;
}
return *this;
}

运算符 *(bigInt( 函数返回错误的答案。例如,33 * 4 返回 1212 而不是 132。这是我尝试编写重载运算符*,它需要一个 bigint 对象:

BigInt BigInt::operator*(BigInt bigN) {
int carry = 0;
for (int i = bigN.storage.size()-1; i >= 0; i--) {
    for (int j = this->storage.size()-1; j >= 0; j--) {
        int val = (this->storage.at(i) * bigN.storage.at(j)) + carry;
        this->storage.push_back(val % 10);
        carry = val / 10;
    }
}
return *this;
}

看起来携带中的逻辑有缺陷,但我不确定如何解决它。

我不确定您是如何尝试执行此操作的,但以下是为什么您会得到结果 1212 而不是 132 的演练:

BigInt operator*(int x)// x is 4
    {
        // Let's say storage holds 33, that's
        // {3, 3} in your char vector;
        int extra = 0;
        int dec_mod = pow(10, this->storage.size()); // dec_mod may be 100

        for (auto & g : storage) 
        {
            g = g * x + extra;  // same as g = 3 * 4 + 0, g = 12
            int mod_g = g % dec_mod; // same as mod_g = 12 % 100 = 12
            extra = g / dec_mod; // same as 12 / 100 = 0
            g = mod_g;  // g = 12
        }
        // Exact same thing happens on the second iteration, your storage vector
        // ends up as {12, 12};
        // That's why your result is 1212
        while (extra > 0) {
            storage.push_back(extra % dec_mod);
            extra /= dec_mod;
        }
        return *this;
    }

我不确定你是如何尝试的,但这是我的尝试,就像在纸上做的那样:

#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct BigInt
{
    BigInt(std::string num) { for (auto &i : num) storage.push_back(i - 48); }
    BigInt(std::vector<char> numVect) : storage(numVect) {}
    vector<char> storage;
    string getAsString() 
    { string str; for (auto& i : storage) str += i + 48; return str; }
    // Add 48 to turn 0 - 9 to ascii string.
    vector<char> add(vector<char>& lhs, vector<char>& rhs)
    // Add function only needed if number is multiplied by more than one digit.
    {
        // Fill with zeros to make both vectors same length.
        int sizeDiff = (int)lhs.size() - (int)rhs.size();
        if (sizeDiff < 0)
            lhs.insert(lhs.begin(), abs(sizeDiff), 0);
        else if (sizeDiff > 0)
            rhs.insert(rhs.begin(), abs(sizeDiff), 0);
        vector<char> resultVect;
        int carry = 0;
        for (int i = lhs.size() - 1; i >= 0; --i)
        {
            int result = lhs[i] + rhs[i] + carry;
            carry = result / 10;
            result %= 10;
            resultVect.insert(resultVect.begin(), result);
        }
        if (carry != 0) resultVect.insert(resultVect.begin(), carry);
        return resultVect;
    }
    BigInt operator*(BigInt rhs)
    {
        int unitPlace = 0; // Keeps track of how many zeros to add in subsequent results
        vector<char> totalVect; // Accumulated value after each addition
        vector<char> resultVect; // Result of this particular multiplication
        for (int i = rhs.storage.size() - 1; i >= 0; --i, unitPlace++)
        {
            int carry = 0;
            for (int k = 0; k < unitPlace; ++k) resultVect.push_back(0);
            for (int j = storage.size() - 1; j >= 0; j--)
            {
                int result = rhs.storage[i] * storage[j] + carry;
                carry = result / 10;
                result %= 10;
                resultVect.insert(resultVect.begin(), result);
            }
            resultVect.insert(resultVect.begin(), carry);
            totalVect = add(totalVect, resultVect); // Add sub-result
            resultVect.clear();
        }
        // Strip leading zeros
        for (int i = 0; i < totalVect.size(); ++i) {
            if (totalVect[i] == 0) totalVect.erase(totalVect.begin() + i);
            else break;
        }
        return BigInt{ totalVect };
    }
};
int main()
{
    BigInt a{ "335467" };
    BigInt b{ "1019737" };
    BigInt c = a * b;
    std::cout << c.getAsString() << 'n';
    cin.ignore();
    return 0;
}