BigInt乘法和减法误差

问题描述 投票:-1回答:1

我要分配一个计算器,该计算器可以处理长度不超过256个字符的大整数。我收到的错误消息无法解决多个减法数问题,例如23456-13141 = 10315,但是其他任何减法(例如6-5)均不起作用。我很困惑为什么会这样。

下面的完整代码

#include <iostream>   
#include <string> 
#include "Bigint.h" 

using namespace std; 

Bigint::Bigint() 
{
    for (int i = DIGITS-1; i >= 0; --i) {
        digits_[i] = 0;
    }
    radix = 10;
}

Bigint::Bigint(int r)  
{
    for (int i = DIGITS-1; i >= 0; --i) {
        digits_[i] = 0;
    }
    radix = r;
}

ostream& operator<< (ostream& out, const Bigint& n) 
{
    string s = "";
    int leadingZeros = 0;

    for (int i = DIGITS-1; i >= 0 ; --i) { 

        if(n.digits_[i] != 0){      
            leadingZeros = 1;
        }

        if(leadingZeros == 1){
            s += char(n.digits_[i] + '0'); 
        }
    }
    return out << s;
}

istream& operator>> (istream& in, Bigint& n)
{

    string s;
    if (in >> s) {

        int length = s.length(); 
        int i;
        for (i = 0; i < DIGITS && i < length; ++i) {
            n.digits_[i] = int(s[length-1 - i] - '0'); 
        }
    }
    return in;
}

Bigint operator+ (const Bigint& n1, const Bigint& n2)
{
    Bigint add;
    int carry = 0, sum = 0;

    for(int i=0; i < DIGITS; ++i){ 
        sum = n1.digits_[i] + n2.digits_[i] + carry; 
        add.digits_[i] = sum % 10;
        carry = sum / 10;
    }
    return add;
}

Bigint operator- (const Bigint& n1, const Bigint& n2) 
{
    Bigint sub;
    int carry = 0; 
    for (int i=0; i< DIGITS; i++) 
    { 

        int val = n1.digits_[i] - n2.digits_[i] -carry;  

        if (val < 0) 
        { 
            val += 10; 
            carry = 1; 
        } 
        else
            carry = 0; 

        sub.digits_[i] = val;
    } 
    return sub;
}

Bigint Bigint :: multiplyBigint(const Bigint& num, const int n, int count){ 

    Bigint result;
    int carry =0;

    for(int i=0; i< DIGITS; ++i){
        int val = (num.digits_[i] * n) + carry;
        result.digits_[i+count] = val % 10;
        carry = val / 10; 
    }

    return result;
}

Bigint operator* (const Bigint& n1, const Bigint& n2)
{
    Bigint multiply;
    Bigint temp;

    int count =0;

    for(int i=0; i< DIGITS; ++i){
        temp = Bigint :: multiplyBigint(n1, n2.digits_[i], count);
        count++;
        multiply = multiply + temp;
    }

    return multiply;
}

Bigint operator/ (const Bigint& n1, const Bigint& n2)
{
    Bigint divide;
    Bigint temp = n1;

    while(temp > n2){
        divide = divide + 1;
        temp = temp - n2;
    }

    return divide; 
}

Bigint operator+ (const Bigint& n1, int n2)
{
    Bigint add;
    int carry = 0, sum = 0;

    for(int i=0; i < DIGITS; ++i){
        sum = n1.digits_[i] + (n2 % 10) + carry;
        n2 = n2 / 10;
        add.digits_[i] = sum % 10;
        carry = sum / 10;
    }
    return add;
}

bool operator> (const Bigint& n1, const Bigint& n2){

    for(int i= DIGITS - 1; i >= 0; --i){
        if(n1.digits_[i] > n2.digits_[i])
            return true;
    }
    return false;
}

头文件

#ifndef BIGINT_H_ //This checks to whether the given token has been defined somewhere else in the file.
#define BIGINT_H_

#define DIGITS 256 //increases the array size to 256 digits.

class Bigint
{
  public: // this makes the members of the public accessible from anywhere in the project.

    /**
     * Creates a Bigint initialised to 0.
     */
    Bigint(); 
    Bigint(int r);

    /**
     * Inserts n into stream or extracts n from stream.
     */
    friend std::ostream& operator<< (std::ostream &out, const Bigint& n);
    friend std::istream& operator>> (std::istream &in, Bigint& n);

    /**
     * Returns the sum, difference, product, or quotient of n1 and n2 and compares them.
     */
    friend Bigint operator+ (const Bigint& n1, const Bigint& n2);
    friend Bigint operator- (const Bigint& n1, const Bigint& n2);
    friend Bigint operator* (const Bigint& n1, const Bigint& n2);
    friend Bigint operator/ (const Bigint& n1, const Bigint& n2);

    friend Bigint operator+ (const Bigint& n1, int n2);
    friend bool operator> (const Bigint& n1, const Bigint& n2);

  private: //making this only accessible within other members of this same class.
    int digits_[DIGITS];
    int radix;
    static Bigint multiplyBigint(const Bigint& num, const int n, int count);
};

#endif // BIGINT_H_

Main.cpp

#include <iostream> //provides basic input and output services such as char.
#include "Bigint.h" //provides access and link to header file.

using namespace std;

int findRadix(string value){ //uses the Radix sort alogrithm to sort each value.

    if(value.length() == 3){
        if(value[0] == '-' && value[1] == 'r'){
            if(value[2] >= '2' && value[2] <= '9')
                return value[2] - '0';
            else if(value[2] >= 'A' && value[2] <= 'Z')
                return (value[2] - 'A') + 10;
        }
    }

    return 10;
}

int main(int argc, char *argv[]) 
{
    int radix;

    if(argc ==2){
        radix = findRadix(argv[1]);
    }


    Bigint n1(radix), n2(radix); //This compares n1 and n2 to each other to give a result.
    char op;

    while (cin >> n1 >> op >> n2) {
        switch (op) {
        case '+' :
            cout << n1 + n2 << endl;
            break;
        case '-' :
            cout << n1 - n2 << endl;
            break;
        case '*' :
            cout << n1 * n2 << endl;
            break;
        case '/' :
            cout << n1 / n2 << endl;
            break;
        }
    }

    return 0;
}
c++ arrays element digits
1个回答
0
投票

似乎我发现了您的问题-您自己不清洁。也就是说,每次输入新数字时,它也会使用一些旧数字。

有几种可能的解决方案。最简单的方法(带有一些代码修复程序)如下:

在类的某个位置创建方法clear

void Bigint::clear()
{
    for (int i = DIGITS-1; i >= 0; --i)
        digits_[i] = 0;
}

删除默认构造函数(这是可选的,但他是多余的,然后将另一个构造函数更改为此:]

Bigint::Bigint(int radix = 10) : radix{radix}
{
    clear();
}

并在输入运算符的开头添加以下内容:

istream& operator>> (istream& in, Bigint& n)
{
    clear(); //This is the important one!!!!

    string s;
    if (in >> s) {
    ...
    ...
}

还有其他可能的解决方案:

  • 您可以将成员int length;添加到您的班级。输入运算符中已经具有此长度,您只需要保留它并在所有计算中使用它即可。

  • 甚至更好,将digits_更改为std::vector<int> digits_;。这将使您摆脱clear函数,从而使构造函数为空(仅使用成员初始化)。您只需要在输入运算符的开头调用digits_.clear();。并使用digits_.push_back(...);而不是摆弄索引。

但是最正确的解决方案(尽管无论如何都应更改为std::vector<int>)只是删除输入运算符,然后更改Bigint::Bigint以接受字符串。那是:

Bigint::Bigint(std::string s, int radix = 10) : radix{radix}
{
    const int length = s.length();
    for (int i = 0; (i < DIGITS) && (i < length); ++i)
        n.digits_[i] = int(s[length()-1 - i] - '0');
}

此后,您主要执行此操作:

void main(...)
{
    ....

    char op;
    std::string s1, s2;

    while (cin >> s1 >> op >> s2)
    {
        Bigint n1 {s1, radix};
        Bigint n2 {s2, radix};

        switch (op) {
        .....
        }
    }
}

这具有以下好处:

我强烈考虑将您的digits_替换为std::vector<int>。这样做的好处是可以接受any大小的数字,因为向量可以根据您的需要增大。这也将使字符串到int的转换代码更加简单。并且使您[[multiply更简单,因为您可以通过简单的操作轻松在向量的末尾添加零。并且可以避免很多其他错误。只需将其更改为std::vector<int>! ;-)

此外,请注意using namespace std;是不当行为:Why is "using namespace std;" considered bad practice?
© www.soinside.com 2019 - 2024. All rights reserved.