接口完备的高精度整数计算类

接口完备的高精度整数计算类
      做ACM的时候经常会遇到高精题,把自己封装好的高精类跟大家分享。实现方式就是模拟每个位的计算,把每个位的数字保存到数组中。具体实现可以看代码,都有注释。
代码如下:
/*   
        Author: ACb0y
	FileName: BigNumber.cpp
	CreateDate: 2011年10月18日22:50:17
	Version: 1.0
*/  
  
#include <iostream>   
using namespace std;   
  
int const MAXN = 800;   
  
class BigNumber   
{   
public:   
    int s[MAXN];   
    int len;   
public:   
    // 去除前导零   
    void cleanLeadZero();   
    // 乘以10的n次方   
    void multiplyTen(int n);   
    // 除以10的n次方   
    void divisionTen(int n);   
    // 将结果转换成字符串   
    string str() const;   
    // 构造函数   
    BigNumber();   
    BigNumber(int);   
    BigNumber(const char *);   
    // 截取整数的前n位数(例如1234434 调用getSub(3)的话得到的结果是123)   
    BigNumber getSub(int n) const;   
    // 重载赋值运算符   
    BigNumber operator = (const char *);   
    BigNumber operator = (int num);   
    // 重载加减乘除   
    BigNumber operator + (const BigNumber &) const;   
    BigNumber operator - (const BigNumber &) const;   
    BigNumber operator * (const BigNumber &) const;   
    BigNumber operator / (const BigNumber &) const;   
    BigNumber operator % (const BigNumber &) const;   
    BigNumber operator -= (const BigNumber &);   
    BigNumber operator += (const BigNumber &);   
    BigNumber operator *= (const BigNumber &);   
    BigNumber operator /= (const BigNumber &);   
    // 重载比较运算符   
    bool operator < (const BigNumber &) const;   
    bool operator > (const BigNumber &) const;   
    bool operator <= (const BigNumber &) const;   
    bool operator >= (const BigNumber &) const;   
    bool operator == (const BigNumber &) const;   
    // 重载输入输出流   
    friend istream & operator >> (istream &, BigNumber &);   
    friend ostream & operator << (ostream &, BigNumber &);   
  
};   
  
void BigNumber::cleanLeadZero() {   
    while (len > 1 && !s[len - 1]) len--;   
}   
  
void BigNumber::divisionTen(int n)   
{   
    int i;   
    if (n > len) {   
        while (len >= 1) s[len--] = 0;   
    } else {   
        for (i = 0; i < len - n; i++)    
        {   
            s[i] = s[i + n];   
        }   
        len -= n;   
    }   
}   
  
void BigNumber::multiplyTen(int n)   
{   
    if (n > 0) {   
        int i;   
        for (i = len - 1; i >= 0; i--)    
        {   
            s[i + n] = s[i];   
        }   
        for (i = 0; i < n; i++) {   
            s[i] = 0;   
        }   
        len += n;   
    }   
}   
  
string BigNumber::str() const  
{   
    string res = "";   
    // 每个位的数逆序添加到str末尾。   
    for (int i = 0;  i < len; i++) {   
        res = (char)(s[i] + '0') + res;   
    }   
    if (res == "") res = "0";   
    return res;   
}   
  
BigNumber::BigNumber()    
{   
    memset(s, 0, sizeof(s));   
    len = 1;   
}   
  
BigNumber::BigNumber(int num) {   
    *this = num;   
}   
  
BigNumber::BigNumber(const char * num) {   
    *this = num;   
}   
  
BigNumber BigNumber::getSub(int n) const    
{   
    BigNumber c;   
    c.len = 0;   
    for (int i = 0; i < n; i++) {   
        c.s[c.len++] = s[len - n + i];   
    }   
    return c;   
}   
  
BigNumber BigNumber::operator = (const char * num)    
{   
    len = strlen(num);   
    // 整数在s数组中是逆序存放的(如:"456" 在s数组中是s[0] = 6, s[1] = 5, s[2] = 4)   
    for (int i = 0; i < len; i++) {   
        s[i] = num[len - i - 1] - '0';   
    }   
    return *this;   
}   
  
BigNumber BigNumber::operator = (int num) {   
    char s[MAXN];   
    sprintf(s, "%d", num);   
    *this = s;   
    return *this;   
}   
  
BigNumber BigNumber::operator + (const BigNumber & x) const  
{   
    BigNumber r;   
    r.len = 0;   
    // up 是用来保持进位的   
    int i, up;   
    int maxLen = max(len, x.len);   
    for (i = 0, up = 0; up || i < maxLen; i++) {   
        int temp = up;   
        if (i < len) temp += s[i];   
        if (i < x.len) temp += x.s[i];   
        up = temp / 10;   
        r.s[r.len++] = temp % 10;   
    }   
    // 去除前导零   
    r.cleanLeadZero();   
    return r;   
}   
  
// 减法在使用时要注意在计算a - b时要确保a >= b;   
// 如果a < b 则计算 先输出一个'-' 再输出b - a 的结果   
BigNumber BigNumber::operator - (const BigNumber & b) const    
{   
    BigNumber c;   
    c.len = 0;   
    int i;   
    // 用来保存退位   
    int down;   
    for (i = 0, down = 0; i < len; i++)    
    {   
        int temp = s[i] - down;   
        if (i < b.len) temp  -= b.s[i];   
        if (temp >= 0) down = 0;   
        else {   
            down = 1;   
            temp += 10;   
        }   
        c.s[c.len++] = temp;   
    }   
    c.cleanLeadZero();   
    return c;   
}   
  
BigNumber BigNumber::operator * (const BigNumber & b) const  
{   
    int i, j;   
    BigNumber c;   
    c.len = len + b.len;   
    for (i = 0; i < len; i++) {   
        for (j = 0; j < b.len; j++) {   
            c.s[i + j] += s[i] * b.s[j];   
        }   
    }   
       
    for (i = 0; i < c.len - 1; i++) {   
        c.s[i + 1] += c.s[i] / 10;   
        c.s[i] %= 10;   
    }   
    c.cleanLeadZero();   
    return c;   
}   
  
BigNumber BigNumber::operator / (const BigNumber & b) const  
{   
    int i, j;   
    BigNumber r;   
    r.len = 0;   
    // 模拟除法的过程   
    // 先取blen - 1位   
    BigNumber temp = this->getSub(b.len - 1);   
    // 一位一位的除从而取得完整的答案   
    for (i = len - b.len; i >= 0; i--)    
    {   
        // temp用来存储被除数的前blen位。   
        temp = temp * 10 + s[i];   
        // 如果temp < b则再在该位的结果为0   
        if (temp < b) {   
            r.s[r.len++] = 0;   
        } else {   
            // 否则找到第一个j使得b * j的结果大于 temp   
            for (j = 1; j <= 10; j++) {   
                if (b * j > temp) break;   
            }   
            // 因为此时(j - 1) * b小于等于temp,所有j - 1就是在该位除的结果   
            r.s[r.len++] = j - 1;   
            // temp 减去被减去部分为下一次迭代做准备   
            temp = temp - (b * (j - 1));   
        }   
    }   
    // 逆序(因为结果是要逆序存储的,而在求解过程中结果是顺序存储的)   
    for (i = 0; i < r.len / 2; i++) {   
        int temp = r.s[i];   
        r.s[i] = r.s[r.len - 1 - i];   
        r.s[r.len - 1 - i] = temp;   
    }   
    r.cleanLeadZero();   
    return r;   
}   
  
BigNumber BigNumber::operator % (const BigNumber & b) const    
{   
    BigNumber r;   
    r = *this / b;   
    //cout << r << endl;   
    r = *this - r * b;   
    return r;   
}   
  
BigNumber BigNumber::operator += (const BigNumber & b)    
{   
    *this = *this + b;   
    return *this;   
}   
  
BigNumber BigNumber::operator -= (const BigNumber & b)   
{   
    *this = *this - b;   
    return *this;   
}   
  
BigNumber BigNumber::operator *= (const BigNumber & b)   
{   
    *this = *this * b;   
    return *this;   
}   
  
BigNumber BigNumber::operator /= (const BigNumber & b)    
{   
    *this = *this / b;   
    return *this;   
}   
  
bool BigNumber::operator < (const BigNumber & b) const  
{   
    if (len != b.len) return len < b.len;   
    else {   
        for (int i = len - 1; i >= 0; i--) {   
            if (s[i] != b.s[i]) return s[i] < b.s[i];   
        }   
    }   
    return false;   
}   
  
bool BigNumber::operator > (const BigNumber & b) const  
{   
    return b < *this;   
}   
  
bool BigNumber::operator <= (const BigNumber & b) const  
{   
    return !(b > *this);   
}   
  
bool BigNumber::operator >= (const BigNumber & b) const  
{   
    return !(*this < b);   
}   
  
bool BigNumber::operator == (const BigNumber & b) const  
{   
    return !(b < *this) && !(b > *this);   
}   
  
istream & operator >> (istream & in, BigNumber & x)   
{   
    string s;   
    in >> s;   
    x = s.c_str();   
    return in;    
}   
  
ostream & operator << (ostream & out, BigNumber & x)   
{   
    out << x.str();   
    return out;   
}   
  
int main()   
{    
	char a[1000];   
	char b[1000];   
	char op;  
	//输入重定向到in.dat文件
    freopen("in.txt", "r", stdin);    
    while (scanf("%s %c %s", a, &op, b) != EOF) {   
        BigNumber lvalue(a);   
        BigNumber rvalue(b);  
		//去掉前导零
        lvalue.cleanLeadZero();   
        rvalue.cleanLeadZero();   
		cout << lvalue << " " << op << " " << rvalue << " = ";
        switch (op) 
		{
		case '+':
		
			cout << (lvalue + rvalue).str() << endl;
			break;
		case '-':
			cout << (lvalue - rvalue).str() << endl;
			break;
		case '*':
			cout << (lvalue * rvalue).str() << endl;
			break;
		case '/':
			cout << (lvalue / rvalue).str() << endl;
			break;
		case '%':
			cout << (lvalue % rvalue).str() << endl;
			break;
		}
    } 
    return 0;   
}
测试数据:

测试结果:


阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ACb0y/article/details/6886465
想对作者说点什么? 我来说一句

整数高精度计算

2012年06月05日 7KB 下载

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭