c ++中的大数字实现

时间:2014-12-28 06:09:14

标签: c++ bignum

我正在尝试使用字符串在c ++中实现Big Number。 首先,我为'+'运算符执行运算符重载,添加数字长度> 3是正确的但是小于3是在结果之后给出垃圾值。我不明白为什么会这样。 这是我的代码。

#include<iostream>
#include<cstring>
#define SIZE 100
using namespace std;
class BigNumber
{
    char *chNumber;
    long nLength,nMaxLength;
    public :
        BigNumber()
        {
            nLength = nMaxLength = 0;
            Init();
        }
        BigNumber(long length)
        {
            nLength = length;
            nMaxLength = length;
            Init();
        }
        BigNumber(const char *str,long length)
        {
            nLength = strlen(str);
            nMaxLength = length;            
            Init();
            memset(chNumber,0,sizeof(char));
            strncpy(chNumber,str,length);
        }
        /*** copy constructor **/
        BigNumber(const BigNumber &source)
        {
            nLength = strlen(source.chNumber);
            nMaxLength = source.nMaxLength;
            if(source.chNumber)
            {
                Init();
                strncpy(chNumber,source.chNumber,nLength);
            }
            else
                chNumber = 0;
        }
        void Init()
        {
            chNumber = new char[nMaxLength + 5];
            memset(chNumber,0,sizeof(char));
        }
        ~BigNumber()
        {
            delete[] chNumber;
            chNumber = 0;
            nLength = 0;
        }
        char* getNumber()
        {
            return chNumber;
        }
        const long size() const
        {
            return nLength;
        }
        const long capacity() const
        {
            return nMaxLength;
        }
        friend long maxsize(BigNumber &obj1,BigNumber &obj2) 
        {
            return (obj1.size() > obj2.size()) ? obj1.size():obj2.size();
        }
        friend ostream& operator<<(ostream &out,BigNumber &obj)
        {
            //out<<"String is "<<obj.chNumber<<" of length "<<obj.nLength
            //  <<" and max length allocated is "<<obj.nMaxLength;
            out<<obj.chNumber;
            return out;
        }

        friend istream& operator>>(istream &in,BigNumber &obj)
        {
            obj.Init();
            in>>obj.chNumber;
            obj.nLength = strlen(obj.chNumber);
            return in;
        }   
        BigNumber &operator=(const BigNumber &obj)
        {
            if(this == &obj)
            {
                return *this;
            }
            delete[] chNumber;
            chNumber = 0;
            nLength = strlen(obj.chNumber);
            Init();
            strncpy(chNumber,obj.chNumber,nLength);
            return *this;
        }
        void operator=(char * str)
        {
            nLength = strlen(str);
            Init();
            strncpy(chNumber,str,nLength);
        }
        friend BigNumber reverse(const BigNumber &obj1)
        {
            long length = obj1.size();
            int m=0;
            BigNumber obj2(length+5);
            for(int i=length-1;i>=0;--i)
            {
                obj2.chNumber[m++]=obj1.chNumber[i];
            }
            obj2.chNumber[m]='\0';
            //cout<<obj2.chNumber<<endl;
            obj2.nLength = m;
            return obj2;
        }
        friend BigNumber operator+(BigNumber &obj1,BigNumber &obj2)
        {
            long newLength = maxsize(obj1,obj2);
            BigNumber obj3(newLength + 5);
            int length1 = obj1.size();
            int length2 = obj2.size();
            int i,j,carry=0,num,m=0;
            for(i=length1-1,j=length2-1; i>=0 || j>=0 ; --i,--j)
            {
                if(i>=0 && j>=0)
                {
                    num = (obj1.chNumber[i]-'0') + (obj2.chNumber[j]-'0') + carry;
                }
                else if(i>=0)
                {
                    num = obj1.chNumber[i] - '0' + carry;
                }
                else if(j>=0)
                {
                    num = obj2.chNumber[j] - '0' + carry;
                }
                carry = num/10;
                num = num%10;
                obj3.chNumber[m++] = num+'0';
            }
            obj3.chNumber[m]='\0';
            obj3.nLength = m; 
            BigNumber obj4 = reverse(obj3);
            cout<<obj4<<endl;
            return reverse(obj3);
        }
};

void test_addition()
{
    BigNumber n1("42",3),n2("1",2),n3;
    n3 = n1 + n2;
    cout<<n3<<endl;
    n1 = "123";
    n2 = "345";
    n3 = n1 + n2;
    cout<<n3<<endl;
}
int main()
{
    test_addition();
    return 0;
}

在从操作符+()函数返回之前,我正在打印它给出正确的输出,并且在返回之后我打印的是在结果之后给出垃圾值。

谢谢

1 个答案:

答案 0 :(得分:2)

您的实施中存在一些问题,即:

  1. 内存管理不善
  2. 缺少复制构造函数
  3. 循环退出后,
  4. operator+不计算非零carry,或者说明总和可能比两个输入值的长度更长的可能性。
  5. 请改为尝试:

    #include <iostream>
    #include <cstring>
    #include <iomanip>
    
    #define SIZE 100
    
    class BigNumber
    {
    private:
        char *chNumber;
        long nLength, nMaxLength;
    
        public :
            BigNumber()
            {
                nLength = nMaxLength = 0;
                Init();
            }
    
            BigNumber(long initialCapacity)
            {
                nLength = 0;
                nMaxLength = initialCapacity;
                Init();
            }
    
            BigNumber(const char *str)
            {
                nLength = nMaxLength = strlen(str);
                Init();
                memcpy(chNumber, str, nLength);
            }
    
            BigNumber(const BigNumber &source)
            {
                nLength = source.nLength;
                nMaxLength = source.nMaxLength;
                Init();
                memcpy(chNumber, source.chNumber, nLength);
            }
    
            void Init()
            {
                chNumber = new char[nMaxLength + 5];
                memset(chNumber, 0, nMaxLength + 5);
            }
    
            ~BigNumber()
            {
                delete[] chNumber;
                chNumber = 0;
                nLength = nMaxLength = 0;
            }
    
            const char* getNumber() const
            {
                return chNumber;
            }
    
            const long size() const
            {
                return nLength;
            }
    
            const long capacity() const
            {
                return nMaxLength;
            }
    
            friend long maxsize(const BigNumber &obj1, const BigNumber &obj2)
            {
                return (obj1.size() > obj2.size()) ? obj1.size(): obj2.size();
            }
    
            friend ostream& operator<<(ostream &out, const BigNumber &obj)
            {
                //out<<"String is "<<obj.chNumber<<" of length "<<obj.nLength
                //  <<" and max length allocated is "<<obj.nMaxLength;
                out << obj.chNumber;
                return out;
            }
    
            friend istream& operator>>(istream &in, BigNumber &obj)
            {
                char tmp[SIZE+1];
                memset(tmp, 0, SIZE);
                in >> setw(SIZE) >> tmp;
                obj = tmp;
                return in;
            }
    
            BigNumber &operator=(const BigNumber &obj)
            {
                if (this != &obj)
                {
                    delete[] chNumber;
                    chNumber = 0;
                    nLength = obj.nLength;
                    nMaxLength = obj.nMaxLength;
                    Init();
                    memcpy(chNumber, obj.chNumber, nLength);
                }
                return *this;
            }
    
            BigNumber& operator=(const char* str)
            {
                delete[] chNumber;
                chNumber = 0;
                nLength = nMaxLength = strlen(str);
                Init();
                memcpy(chNumber, str, nLength);
            }
    
            friend BigNumber reverse(const BigNumber &obj1)
            {
                long length = obj1.size();
                int m = 0;
                BigNumber obj2(length);
                for(int i = length-1; i >= 0; --i)
                {
                    obj2.chNumber[m++] = obj1.chNumber[i];
                }
                obj2.chNumber[m] = '\0';
                //cout << obj2.chNumber << endl;
                obj2.nLength = m;
                return obj2;
            }
    
            friend BigNumber operator+(const BigNumber &obj1, const BigNumber &obj2)
            {
                long newCapacity = maxsize(obj1, obj2) + 1;
                BigNumber obj3(newCapacity);
                int length1 = obj1.size();
                int length2 = obj2.size();
                int carry = 0, num, m = 0;
                for(int i = length1-1, j = length2-1; (i >= 0) || (j >= 0); --i, --j)
                {
                    if ((i >= 0) && (j >= 0))
                    {
                        num = (obj1.chNumber[i]-'0') + (obj2.chNumber[j]-'0') + carry;
                    }
                    else if (i >= 0)
                    {
                        num = obj1.chNumber[i] - '0' + carry;
                    }
                    else
                    {
                        num = obj2.chNumber[j] - '0' + carry;
                    }
                    carry = num/10;
                    num %= 10;
                    obj3.chNumber[m++] = num+'0';
                }
                if (carry != 0)
                    obj3.chNumber[m++] = carry+'0';
                obj3.chNumber[m]='\0';
                obj3.nLength = m;
                return reverse(obj3);
            }
    };
    

    话虽如此,我强烈建议您更改内部缓冲区以使用std::string而不是char[]数组,并使用标准STL函数而不是编写自己的函数。这将简化实现:

    #include <iostream>
    #include <cstring>
    #include <iomanip>
    #include <algorithm>
    
    #define SIZE 100
    
    class BigNumber
    {
    private:
        std::string chNumber;
    
    public:
        BigNumber()
        {
        }
    
        BigNumber(const BigNumber &src)
            : chNumber(src.chNumber)
        {
        }
    
        BigNumber(long initialCapacity)
        {
            chNumber.reserve(initialCapacity);
        }
    
        BigNumber(const char *str)
            : chNumber(str)
        {
        }
    
        const char* getNumber() const
        {
            return chNumber.c_str();
        }
    
        const long size() const
        {
            return chNumber.size();
        }
    
        const long capacity() const
        {
            return chNumber.capacity();
        }
    
        friend ostream& operator<<(ostream &out, const BigNumber &obj)
        {
            //out<<"String is " << obj.chNumber << " of length " << obj.size()
            //  << " and max length allocated is " << obj.capacity();
            out << obj.chNumber.c_str();
            return out;
        }
    
        friend istream& operator>>(istream &in, BigNumber &obj)
        {
            char tmp[SIZE+1];
            memset(tmp, 0, SIZE);
            in >> std::setw(SIZE) >> tmp;
            obj = tmp;
            return in;
        }
    
        BigNumber& operator=(const BigNumber &obj)
        {
            chNumber = obj.chNumber;
            return *this;
        }
    
        friend BigNumber operator+(const BigNumber &obj1, const BigNumber &obj2)
        {
            BigNumber obj3(std::max(obj1.size(), obj2.size())+1);
            int length1 = obj1.size();
            int length2 = obj2.size();
            int carry=0, num;
            for (int i = length1-1, j = length2-1; (i >=0) || (j >= 0); --i,--j)
            {
                if ((i >= 0) && (j >= 0))
                {
                    num = (obj1.chNumber[i] - '0') + (obj2.chNumber[j] - '0') + carry;
                }
                else if (i >= 0)
                {
                    num = (obj1.chNumber[i] - '0') + carry;
                }
                else
                {
                    num = (obj2.chNumber[j] - '0') + carry;
                }
                carry = num / 10;
                num %= 10;
                obj3.chNumber += ('0'+num);
            }
            if (carry != 0)
                obj3.chNumber += ('0'+carry);
            std::reverse(obj3.chNumber.begin(), obj3.chNumber.end());
            return obj3;
        }
    };
    
    void test_addition()
    {
        BigNumber n1("42"), n2("1"), n3;
        n3 = n1 + n2;
        std::cout << n3 << std::endl;
        n1 = "123";
        n2 = "345";
        n3 = n1 + n2;
        std::cout << n3 << std::endl;
    }
    
    int main()
    {
        test_addition();
        return 0;
    }