编程语言

img hippoz

[原创]最近学习STL,在C++库中苦寻不到BigInteger类,于是自己写了一个

发表于2004/10/4 19:38:00  1633人阅读

// big_integer.h

#include <string>
#include <vector>
#include <iostream>

using namespace std;

class NumberFormatException
{
    private:
        string str;
    public:
        NumberFormatException(string);
        friend ostream& operator<<(ostream&,const NumberFormatException&);
};
class DividedByZeroException
{
    private:
        string str;
    public:
        DividedByZeroException(string);
        friend ostream& operator<<(ostream&,const DividedByZeroException&);

};
class big_integer
{
    private:
        vector<char> digits;    //
        bool sign;      //  true for positive, false for negitive
        void trim();        //  remove zeros in tail, but if the value is 0, keep only one:)
    public:
        explicit big_integer(long); // construct with a long integer
        explicit big_integer(string&)throw(NumberFormatException);
        // construct with a string, which must be all integers-bits
        // a sign can also be included. if the format is wrong, this will generate an Exception

        big_integer(const big_integer&);
        big_integer operator=(const big_integer& op2){
            digits = op2.digits;
            sign = op2.sign;
            return (*this);
        }
        big_integer abs()const{
            if( sign )  return *this;
            else    return -(*this);
        }

        //binary operators

        friend big_integer operator+=(big_integer&,const big_integer&);
        friend big_integer operator-=(big_integer&,const big_integer&);
        friend big_integer operator*=(big_integer&,const big_integer&);
        friend big_integer operator/=(big_integer&,const big_integer&)throw(DividedByZeroException);
        friend big_integer operator%=(big_integer&,const big_integer&)throw(DividedByZeroException);       

        friend big_integer operator+(const big_integer&,const big_integer&);
        friend big_integer operator-(const big_integer&,const big_integer&);
        friend big_integer operator*(const big_integer&,const big_integer&);
        friend big_integer operator/(const big_integer&,const big_integer&)throw(DividedByZeroException);
        friend big_integer operator%(const big_integer&,const big_integer&)throw(DividedByZeroException);
   

        //uniary operators
        friend big_integer operator-(const big_integer&);   //negative

        friend big_integer operator++(big_integer&);        //++v
        friend big_integer operator++(big_integer&,int);    //v++
        friend big_integer operator--(big_integer&);        //--v
        friend big_integer operator--(big_integer&,int);    //v--

        friend bool operator>(const big_integer&,const big_integer&);
        friend bool operator<(const big_integer&,const big_integer&);
        friend bool operator==(const big_integer&,const big_integer&);
        friend bool operator!=(const big_integer&,const big_integer&);
        friend bool operator>=(const big_integer&,const big_integer&);
        friend bool operator<=(const big_integer&,const big_integer&);

        friend ostream& operator<<(ostream&,const big_integer&);    //print the big_integer
};
const big_integer ZERO(0);
const big_integer ONE(1);


// big_integer.cpp

#include <list>
#include <deque>
#include <vector>
#include <iostream>
#include <string>
#include <algorithm>
#include <functional>
#include "big_integer.h"

using namespace std;

NumberFormatException::NumberFormatException(string s):str(s){}
ostream& operator<<(ostream& stream,const NumberFormatException& exception){
    stream << exception.str;
    return stream;
}

DividedByZeroException::DividedByZeroException(string s):str(s){}
ostream& operator<<(ostream& stream,const DividedByZeroException& exception){
    stream << exception.str;
    return stream;
}


big_integer::big_integer(long val){// construct with a long integer
    if (val >= 0){
        sign = true;
    }else{
        sign = false;
        val *= (-1);
    }
    do{
        digits.push_back( (char)(val%10) );
        val /= 10;
    }while ( val != 0 );
    trim();
}
void big_integer::trim(){
    vector<char>::reverse_iterator iter = digits.rbegin();
    while(iter != digits.rend() && (*iter) == '/0'){
        digits.pop_back();
        iter++;
    }
    if( digits.size()==0 ){
        sign = true;
        digits.push_back('/0');
    }
}


// construct with a string, which must be all integers-bits
// a sign can also be included. if the format is wrong, this will generate an Exception

big_integer::big_integer(string& def)throw(NumberFormatException){

    for ( string::reverse_iterator iter = def.rbegin() ; iter < def.rend();  iter++){
        char ch = (*iter);
        if (iter == def.rend()-1){
            if ( ch == '+' ){
                sign = true;
                continue;
            }
            else if(ch == '-' ){
                sign = false;
                continue;
            }
        }
        if (ch <'0' || ch >'9'){
            throw NumberFormatException(string("整数格式不对哦"));
        }
        digits.push_back( (char)((*iter) - '0' ) );
    }
    if( digits.empty() ){
        throw NumberFormatException(string("整数格式不对哦"));
    }
    trim();
}
big_integer::big_integer(const big_integer& op2):digits(op2.digits){
    sign = op2.sign;
}

//binary operators
big_integer operator+=(big_integer& op1,const big_integer& op2){
    if( !!op1.sign == !!op2.sign ){     //只处理相同的符号的情况,异号的情况给-处理
        vector<char>::iterator iter1;
        vector<char>::const_iterator iter2;
        iter1 = op1.digits.begin();
        iter2 = op2.digits.begin();
        char to_add = 0;        //进位

        while ( iter1 != op1.digits.end() && iter2 != op2.digits.end()){
            (*iter1) = (*iter1) + (*iter2) + to_add;
            to_add = (*iter1) / 10;
            (*iter1) = (*iter1) % 10;
            iter1++;iter2++;
        }
        while ( iter1 != op1.digits.end() ){
            (*iter1) = (*iter1) + to_add;
            to_add = (*iter1) / 10;
            (*iter1) %= 10;
            iter1++;
        }
        while ( iter2 != op2.digits.end() ){
            char val = (*iter2) + to_add;
            to_add = val / 10;
            val %= 10;
            op1.digits.push_back(val);
            iter2++;
        }
        if( to_add != 0 ){
            op1.digits.push_back(to_add);
        }
        return op1;
    }else{
        if (op1 > ZERO){
            return op1 -= (-op2);
        }else{
            return op1 = (op2 - (-op1) );
        }
    }

}
big_integer operator-=(big_integer& op1,const big_integer& op2){
    if (op2 < ZERO )    return op1 += (-op2);
    if( op1 < op2 )     return op1 = -(op2-op1);

    if( !!op1.sign == !!op2.sign ){     //只处理相同的符号的情况,异号的情况给+处理
        vector<char>::iterator iter1;
        vector<char>::const_iterator iter2;
        iter1 = op1.digits.begin();
        iter2 = op2.digits.begin();

        char to_substract = 0;  //借位

        while ( iter1 != op1.digits.end() && iter2 != op2.digits.end()){
            (*iter1) = (*iter1) - (*iter2) - to_substract;
            to_substract = 0;
            while( (*iter1) < 0 ){
                to_substract++;
                (*iter1) += 10;
            }
            iter1++;iter2++;
        }
        while ( iter1 != op1.digits.end() ){
            (*iter1) = (*iter1) - to_substract;
            to_substract = 0;
            while( (*iter1) < 0 ){
                to_substract++;
                (*iter1) += 10;
            }
            iter1++;
        }
        op1.trim();
        return op1;
    }else{
        if (op1 > ZERO){
            return op1 += (-op2);
        }else{
            return op1 = -(op2 + (-op1));
        }
    }
}
big_integer operator*=(big_integer& op1,const big_integer& op2){
    big_integer result(0);
    if (op1 == ZERO || op2==ZERO){
        result = ZERO;
    }else{
        vector<char>::const_iterator iter2 = op2.digits.begin();
        while( iter2 != op2.digits.end() ){
            if(*iter2 != 0){
                deque<char> temp(op1.digits.begin() , op1.digits.end());
                char to_add = 0;
                deque<char>::iterator iter1 = temp.begin();
                while( iter1 != temp.end() ){
                    (*iter1) *= (*iter2);
                    (*iter1) += to_add;
                    to_add = (*iter1) / 10;
                    (*iter1) %= 10;
                    iter1++;
                }
                if( to_add != 0)
                    temp.push_back( to_add );
                int num_of_zeros = iter2 - op2.digits.begin();
                while( num_of_zeros != 0 ){
                    temp.push_front('/0');
                    num_of_zeros--;
                }
               
                big_integer temp2(0);
                temp2.digits.pop_back();
                temp2.digits.insert( temp2.digits.end() , temp.begin() , temp.end() );

                temp2.trim();
                result = result + temp2;
            }
            iter2++;
        }
        result.sign = ( (op1.sign && op2.sign) || (!op1.sign && !op2.sign) );
    }
    op1 = result;
    return op1;
}
big_integer operator/=(big_integer& op1 , const big_integer& op2 )throw(DividedByZeroException){
    if( op2 == ZERO ){
        throw DividedByZeroException("除数遇到0");
    }
    big_integer t1 = op1.abs(),t2 = op2.abs();
    if ( t1 < t2 ){
        op1 = ZERO;
        return op1;
    }
    //现在 t1 > t2 > 0
    //只需将 t1/t2的结果交给result就可以了
    deque<char> temp;
    vector<char>::reverse_iterator iter = t1.digits.rbegin();

    big_integer temp2(0);
    while( iter != t1.digits.rend() ){
        temp2 = temp2 * big_integer( 10 ) + big_integer( (int)(*iter) );
        char s = '/0';
        while( temp2 >= t2 ){
            temp2 = temp2 - t2;
            s = s + 1;
        }
        temp.push_front( s );
        iter++;
    }
    op1.digits.clear();
    op1.digits.insert( op1.digits.end() , temp.begin() , temp.end() );
    op1.trim();
    op1.sign = ( (op1.sign && op2.sign) || (!op1.sign && !op2.sign) );
    return op1;
}
big_integer operator%=(big_integer& op1,const big_integer& op2)throw(DividedByZeroException){
    return op1 -= ((op1 / op2)*op2);
}

big_integer operator+(const big_integer& op1,const big_integer& op2){
    big_integer temp(op1);
    temp += op2;
    return temp;
}
big_integer operator-(const big_integer& op1,const big_integer& op2){
    big_integer temp(op1);
    temp -= op2;
    return temp;
}

big_integer operator*(const big_integer& op1,const big_integer& op2){
    big_integer temp(op1);
    temp *= op2;
    return temp;

}
big_integer operator/(const big_integer& op1,const big_integer& op2)throw(DividedByZeroException){
    big_integer temp(op1);
    temp /= op2;
    return temp;
}

big_integer operator%(const big_integer& op1,const big_integer& op2)throw(DividedByZeroException){
    big_integer temp(op1);
    temp %= op2;
    return temp;
}

//uniary operators
big_integer operator-(const big_integer& op){   //negative
    big_integer temp = big_integer(op);
    temp.sign = !temp.sign;
    return temp;
}

big_integer operator++(big_integer& op){    //++v
    op += ONE;
    return op;
}
big_integer operator++(big_integer& op,int x){  //v++
    big_integer temp(op);
    ++op;
    return temp;
}
big_integer operator--(big_integer& op){    //--v
    op -= - ONE;
    return op;
}

big_integer operator--(big_integer& op,int x){  //v--
    big_integer temp(op);
    --op;
    return temp;
}

bool operator<(const big_integer& op1,const big_integer& op2){
    if( !!op1.sign != !!op2.sign )
        return !op1.sign && op2.sign;
    else{
        if(op1.digits.size() != op2.digits.size())
            return (op1.sign && op1.digits.size()<op2.digits.size()) || (!op1.sign && op1.digits.size()>op2.digits.size());
        //两个的长度也一样了
        vector<char>::const_reverse_iterator iter1,iter2;
        iter1 = op1.digits.rbegin();iter2 = op2.digits.rbegin();
        while( iter1 != op1.digits.rend() ){
            if(  op1.sign &&  *iter1 < *iter2 ) return true;
            if( !op1.sign &&  *iter1 > *iter2 ) return true;
            iter1++;iter2++;
        }
        return false;
    }
}
bool operator==(const big_integer& op1,const big_integer& op2){
    if( !!op1.sign != !!op2.sign  || op1.digits.size() != op2.digits.size() ){
        return false;
    }
    vector<char>::const_iterator iter1,iter2;
    iter1 = op1.digits.begin();iter2 = op2.digits.begin();
    while( iter1!= op1.digits.end() ){
        if( *iter1 != *iter2 )  return false;
        iter1++;iter2++;
    }
    return true;
}
bool operator!=(const big_integer& op1,const big_integer& op2){
    return !(op1==op2);
}
bool operator>=(const big_integer& op1,const big_integer& op2){
    return (op1>op2) || (op1==op2);
}
bool operator<=(const big_integer& op1,const big_integer& op2){
    return (op1<op2) || (op1==op2);
}
bool operator>(const big_integer& op1,const big_integer& op2){
    return !(op1<=op2);
}

ostream& operator<<(ostream& stream,const big_integer& val){    //print the big_integer
    if (!val.sign){
        stream << "-";
    }
    for ( vector<char>::const_reverse_iterator iter = val.digits.rbegin(); iter != val.digits.rend() ; iter++){
        stream << (char)((*iter) + '0');
    }
    return stream;
}

// test_big_integer.cpp

// 测试程序

#include "big_integer.cpp"
#include <fstream>
#include <iostream>
#include <time>

int main()
{
    big_integer b(1);
    ofstream out;
    big_integer result = ONE;
    for( int i = 1 ; i <= 6 ; i++){
        result *= big_integer(i);
    }
    cout << "6 != /n" << result<<endl;


    return 0;
}


 

阅读全文
0 0

相关文章推荐

img
取 消
img