同样不说废话了:
/*
* 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