c++ 大整數類CCBigInteger 加減法功能的實現
阿新 • • 發佈:2019-01-30
同樣不說廢話了:
/* * ccBigInteger.h * c++_common_codes * * Created by xichen on 12-2-21. * Copyright 2012 cc_team. All rights reserved. * */ #ifndef CC_BIG_INTEGER_H #define CC_BIT_INTEGER_H #include <cstdlib> // a kind of decimal big integer class CCBigInteger { public: CCBigInteger(unsigned value = 0, bool sign = true); CCBigInteger(const char *value = "", bool sign = true); ~CCBigInteger(); public: CCBigInteger(const CCBigInteger &bigInteger); CCBigInteger &operator=(const CCBigInteger &bigInteger); public: inline int len() const { return _len; } inline char charValueAt(int index) const { return _value[index]; } inline int intValueAt(int index) const { return _value[index] - '0'; } public: inline void setLen(int newLen) { _len = newLen; } inline void setCharAt(int index, char newChar) { _value[index] = newChar; } inline void setIntAt(int index, int newInt) { _value[index] = newInt + '0'; } public: bool canGetIntValue() const; // if the unsigned value is overflowed, then returns false unsigned uintValue() const; char *str() const; // the char * format value, 239094843343 returns "239094843343"; caller should free the return value public: CCBigInteger operator+(const CCBigInteger &bigInteger); CCBigInteger operator-(const CCBigInteger &bigInteger); public: CCBigInteger operator-(); // neg public: friend bool operator<=(const CCBigInteger &leftBigInteger, const CCBigInteger &rightBigInteger); bool absLessOrEqual(const CCBigInteger &bigInteger); private: CCBigInteger addWithoutSign(const CCBigInteger &leftBigInteger, const CCBigInteger &rightBigInteger); CCBigInteger subWithoutSign(const CCBigInteger &leftBigInteger, const CCBigInteger &rightBigInteger); private: // when subing, the function is called to update the high position value of the minuend int updateHighPosValue(CCBigInteger &minuend, const CCBigInteger &subtrahend, int pos); private: enum { MACRO_MAX_LEN = 1024 }; private: char _value[MACRO_MAX_LEN]; // "321" means the integer 123, not 321 int _len; // the length of the value, should be less to MACRO_MAX_LEN bool _positive; // is positive or not }; void ccTestCCBigInteger(); #endif
/* * ccBigInteger.cpp * c++_common_codes * * Created by xichen on 12-2-21. * Copyright 2012 cc_team. All rights reserved. * */ #include "ccBigInteger.h" #include <iostream> #include <cmath> #include "ccIOBase.h" using namespace std; CCBigInteger::CCBigInteger(unsigned value, bool sign) { _len = 0; int i = 0; while(value != 0) { _value[i++] = (value % 10) + '0'; value /= 10; } _len = i; _positive = sign; } CCBigInteger::CCBigInteger(const char *value, bool sign) // "123" means the int 123 { _len = 0; if(value != NULL) { for(int i = 0; i < strlen(value); ++i) _value[i] = value[strlen(value) - i - 1]; _len = strlen(value); } _positive = sign; } CCBigInteger::~CCBigInteger() { } CCBigInteger::CCBigInteger(const CCBigInteger &bigInteger) { if(&bigInteger == this) return; strcpy(_value, bigInteger._value); _len = bigInteger._len; _positive = bigInteger._positive; } CCBigInteger &CCBigInteger::operator=(const CCBigInteger &bigInteger) { if(&bigInteger == this) return *this; strcpy(_value, bigInteger._value); _len = bigInteger._len; _positive = bigInteger._positive; return *this; } bool CCBigInteger::canGetIntValue() const { bool ret = true; if(_len > 11) // UINT_MAX 's length is 10 return false; if(_len == 10) { for(int i = _len - 1; i >= 0; --i) { if(UINT_MAX / (int)pow((double)10, i) < _value[i] - '0') { ret = false; break; } } } return ret; } unsigned CCBigInteger::uintValue() const { unsigned ret = 0; int tempLen = _len - 1; while(tempLen >= 0) { ret = 10 * ret + _value[tempLen]; --tempLen; } return ret * (_positive ? 1 : -1); } char *CCBigInteger::str() const { char *temp = (char *)malloc(_len + 2); // one is for _positive memset(temp, 0, _len + 2); int i = 0; if(!_positive) { temp[0] = '-'; ++i; for(; i < _len + 1; ++i) { temp[i] = _value[_len - i]; } } else { for(; i < _len; ++i) { temp[i] = _value[_len - i - 1]; } } return temp; } CCBigInteger CCBigInteger::operator+(const CCBigInteger &bigInteger) { if(_positive && bigInteger._positive) // + + --> + return addWithoutSign(*this, bigInteger); if(_positive && !bigInteger._positive) // + - --> - return subWithoutSign(*this, bigInteger); if(!_positive && bigInteger._positive) // - + --> - return subWithoutSign(bigInteger, *this); if(!_positive && !bigInteger._positive) // - - --> + return -(addWithoutSign(*this, bigInteger)); } CCBigInteger CCBigInteger::operator-(const CCBigInteger &bigInteger) { if(_positive && bigInteger._positive) return subWithoutSign(*this, bigInteger); if(_positive && !bigInteger._positive) return addWithoutSign(*this, -const_cast<CCBigInteger &>(bigInteger)); if(!_positive && bigInteger._positive) return -addWithoutSign(*this, bigInteger); if(!_positive && !bigInteger._positive) return subWithoutSign(bigInteger, *this); } bool operator<=(const CCBigInteger &leftBigInteger, const CCBigInteger &rightBigInteger) { if(!leftBigInteger._positive && rightBigInteger._positive) return true; if(leftBigInteger._positive && !rightBigInteger._positive) return false; if(leftBigInteger._positive && rightBigInteger._positive) return const_cast<CCBigInteger &>(leftBigInteger).absLessOrEqual(rightBigInteger); if(!leftBigInteger._positive && !rightBigInteger._positive) return const_cast<CCBigInteger &>(rightBigInteger).absLessOrEqual(leftBigInteger); } bool CCBigInteger::absLessOrEqual(const CCBigInteger &bigInteger) { if(_len > bigInteger._len) return false; if(_len < bigInteger._len) return true; for(int i = _len; i >= 0; --i) { if(_value[i] > bigInteger._value[i]) return false; if(_value[i] < bigInteger._value[i]) return true; } return true; } CCBigInteger CCBigInteger::operator-() { CCBigInteger ret(true); strncpy(ret._value, _value, _len); ret._len = _len; ret._positive = !_positive; return ret; } CCBigInteger CCBigInteger::addWithoutSign(const CCBigInteger &leftBigInteger, const CCBigInteger &rightBigInteger) { CCBigInteger ret((unsigned)0, true); int minLen = min(leftBigInteger._len, rightBigInteger.len()); int promoteValue = 0; for(int i = 0; i < minLen; ++i) { int temp = leftBigInteger._value[i] - '0' + rightBigInteger.intValueAt(i) + promoteValue; int temp1 = temp / 10; promoteValue = temp1; ret.setIntAt(i, temp - temp1 * 10); } if(leftBigInteger._len > minLen) { for(int i = minLen; i < _len; ++i) { int temp = leftBigInteger._value[i] - '0' + promoteValue; int temp1 = temp / 10; promoteValue = temp1; ret.setIntAt(i, temp - temp1 * 10); } } if(rightBigInteger.len() > minLen) { for(int i = minLen; i < rightBigInteger.len(); ++i) { int temp = rightBigInteger.intValueAt(i) + promoteValue; int temp1 = temp / 10; promoteValue = temp1; ret.setIntAt(i, temp - temp1 * 10); } } int maxLen = max(_len, rightBigInteger.len()); ret.setLen(maxLen); if(promoteValue > 0) { ret.setLen(maxLen + 1); ret.setCharAt(maxLen, promoteValue + '0'); } return ret; } CCBigInteger CCBigInteger::subWithoutSign(const CCBigInteger &leftBigInteger, const CCBigInteger &rightBigInteger) { CCBigInteger tempMinuend(true); CCBigInteger ret(true); bool sign = true; if(const_cast<CCBigInteger &>(leftBigInteger).absLessOrEqual(rightBigInteger)) { tempMinuend = rightBigInteger; sign = false; for(int i = 0; i < leftBigInteger._len; ++i) { int temp = tempMinuend.updateHighPosValue(tempMinuend, leftBigInteger, i); ret.setIntAt(i, temp); } for(int i = leftBigInteger._len; i < tempMinuend._len; ++i) { ret.setIntAt(i, tempMinuend._value[i] - '0'); } if(ret._value[tempMinuend._len - 1] == '0') ret.setLen(tempMinuend._len - 1); else ret.setLen(tempMinuend._len); } else { tempMinuend = leftBigInteger; for(int i = 0; i < rightBigInteger._len; ++i) { int temp = tempMinuend.updateHighPosValue(tempMinuend, rightBigInteger, i); ret.setIntAt(i, temp); } for(int i = rightBigInteger._len; i < tempMinuend._len; ++i) { ret.setIntAt(i, tempMinuend._value[i] - '0'); } if(ret._value[tempMinuend._len - 1] == '0') ret.setLen(tempMinuend._len - 1); else ret.setLen(tempMinuend._len); } return (sign ? ret : -ret); } int CCBigInteger::updateHighPosValue(CCBigInteger &minuend, const CCBigInteger &subtrahend, int pos) { char minuendCh = minuend._value[pos]; char subtrahendCh = subtrahend._value[pos]; if(minuendCh >= subtrahendCh) return minuendCh - subtrahendCh; for(int i = pos + 1; i < minuend._len; ++i) { if(minuend._value[i] - '1' >= 0) { minuend._value[i]--; break; } else { minuend._value[i] = '9'; } } return (10 + minuendCh - subtrahendCh); }
測試程式碼:
void ccTestCCBigInteger() { #if 1 // ok CCBigInteger big1("1234567890"); CCBigInteger big2("23456789010"); CCBigInteger ret = big1 + big2; char *str; str = ret.str(); COUT_2_VAR_ENDL("big1 + big2", str) free(str); ret = big1 - big2; str = ret.str(); COUT_2_VAR_ENDL("big1 - big2", str) free(str); ret = big2 + big1; str = ret.str(); COUT_2_VAR_ENDL("big2 + big1", str) free(str); ret = big2 - big1; str = ret.str(); COUT_2_VAR_ENDL("big2 - big1", str) free(str); big1 = CCBigInteger("200010"); big2 = CCBigInteger("12345"); ret = big1 + big2; str = ret.str(); COUT_2_VAR_ENDL("big1 + big2", str) free(str); ret = big1 - big2; str = ret.str(); COUT_2_VAR_ENDL("big1 - big2", str) free(str); ret = big2 + big1; str = ret.str(); COUT_2_VAR_ENDL("big2 + big1", str) free(str); ret = big2 - big1; str = ret.str(); COUT_2_VAR_ENDL("big2 - big1", str) free(str); big1 = CCBigInteger("21234567890"); big2 = CCBigInteger("23456789010", false); // big2 is: -23456789010 // std::cout << big1.str() << std::endl; // std::cout << big2.str() << std::endl; ret = big1 + big2; str = ret.str(); COUT_2_VAR_ENDL("big1 + big2", str) free(str); ret = big1 - big2; str = ret.str(); COUT_2_VAR_ENDL("big1 - big2", str) free(str); ret = big2 + big1; str = ret.str(); COUT_2_VAR_ENDL("big2 + big1", str) free(str); ret = big2 - big1; str = ret.str(); COUT_2_VAR_ENDL("big2 - big1", str) free(str); big1 = CCBigInteger("920010"); big2 = CCBigInteger("99345"); ret = big1 + big2; str = ret.str(); COUT_2_VAR_ENDL("big1 + big2", str) free(str); ret = big1 - big2; str = ret.str(); COUT_2_VAR_ENDL("big1 - big2", str) free(str); ret = big2 + big1; str = ret.str(); COUT_2_VAR_ENDL("big2 + big1", str) free(str); ret = big2 - big1; str = ret.str(); COUT_2_VAR_ENDL("big2 - big1", str) free(str); #endif }
輸出結果:
big1 + big2 24691356900
big1 - big2 -22222221120
big2 + big1 24691356900
big2 - big1 22222221120
big1 + big2 212355
big1 - big2 187665
big2 + big1 212355
big2 - big1 -187665
big1 + big2 -2222221120
big1 - big2 44691356900
big2 + big1 -2222221120
big2 - big1 -44691356900
big1 + big2 1019355
big1 - big2 820665
big2 + big1 1019355
big2 - big1 -820665
注:
1、#include "ccIOBase.h" 標頭檔案:
/*
* ccIOBase.h
* c++_common_codes
*
* Created by xichen on 12-2-15.
* Copyright 2012 cc_team. All rights reserved.
*
*/
#ifndef CC_IO_BASE_H
#define CC_IO_BASE_H
#include <iostream>
using namespace std;
#define COUT_ENDL(message) std::cout << (message) << std::endl;
#define COUT_LINE(str) std::cout << (str) << std::endl;
#define COUT_2_VAR_ENDL(str1, str2) \
std::cout << (str1) << " " << (str2) << std::endl;
#define PRINT_STARS std::cout << "********************************\n";
#endif