以顺序表存储的大整数运算

来源:互联网 发布:淘宝保健品规则 编辑:程序博客网 时间:2024/05/16 18:11

大整数运算的实现原理

  写一个BigInt(大整数)类,其中数据成员是一个顺序表,用来保存大整数.其方法是将数的每一位数(0~9中的一个)存放在每一个节点中,高位存放在高下标,低位存放在低下标.注意:实现时下标是从1开始的.类中的运算如Add(), Sub()等全用友元函数来实现.类中还有一些辅助的函数,如push_back(), push_front()等是用BigInt的数据成员调用了顺序表中的函数.还有一些其他函数在代码中有所说明.
  顺序表中提供了一些顺序表的基本操作,构造,插入,以及插入时容量不足的处理函数等.

代码

seqlist.h

#ifndef _SEQLIST_H#define _SEQLIST_H#include"utili.h"template<typename Type>class SeqList{public:    SeqList(size_t sz = DEFAULT_SIZE)    {        capacity = sz > DEFAULT_SIZE ? sz : DEFAULT_SIZE;        base = new Type[capacity + 1]; //空出一个0下标        memset(base, 0, sizeof(Type) * (capacity+1));        size = 0;    }    SeqList& operator=(const SeqList &sql)    {        if (this != &sql)        {            Type *new_base = new Type[sizeof(Type) * sql.Capacity()+1]; //申请新空间            memset(new_base, 0, sizeof(Type) * (sql.Capacity()+1)); //赋初始值            for (ulong i = 1; i <= sql.Size(); i++) //赋值数据                new_base[i] = sql.base[i];            delete []base; //释放旧空间            base = new_base; //指向新空间            size = sql.Size();            capacity = sql.Capacity();        }        return *this;    }    ~SeqList()    {        delete []base;        base = NULL;        capacity = size = 0;    }public:    bool isfull()const{return size >= capacity;}    bool isempty()const{return size == 0;}public:    bool push_back(const Type &x)    {//尾部插入        if(isfull() && !Inc()) //顺序不能改变            return false;        base[++size] = x;        return true;    }    bool push_front(const Type &x)    {//头部插入        if (isfull() && !Inc())            return false;        size++;        //移动数据并插入        for (ulong i = size-1; i >= 1; i--)            base[i+1] = base[i];        base[1] = x;        return true;    }public:    bool pop_back()    {//尾部删除        if (isempty())            return false;        base[size--] = 0;    }    bool pop_front();    void reset()    {//顺序表清空        memset(base, 0, sizeof(Type) * (capacity+1));        size = 0;    }public:    ulong Size()    {        return size;    }    ulong Size()const    {        return size;    }    ulong Capacity()    {        return capacity;    }    ulong Capacity()const    {        return capacity;    }public:    Type& operator[](ulong pos)    {        return base[pos];    }    Type& operator[](ulong pos)const    {        return base[pos];    }protected:    bool Inc()    {//空间不足时处理函数        Type *new_base = new Type[capacity + INC_SIZE + 1]; //申请新空间        if (new_base == NULL)            return false;        memset(new_base, 0, sizeof(Type)*(capacity+INC_SIZE+1)); //赋值0        memcpy(new_base, base, sizeof(Type)*(capacity+1)); //数据移动复制        capacity += INC_SIZE; //容量增加INC_SIZE        delete []base; //释放旧空间        base = new_base; //base指向新的空间        return true;    }private:    enum{DEFAULT_SIZE=20, INC_SIZE=10}; //默认大小,增长长度    Type *base; //指向数组空间的指针    ulong capacity; //容量    ulong size; //顺序表大小};#endif

bigint.h

#include "seqlist.h"class BigInt{public:    BigInt();    BigInt(int x);    BigInt& operator=(const BigInt &bt);public:    void LoadData(int sz);      //随机加载一个长度sz的整数    void PrintData()const;      //输出整数    ulong size()const;      //返回整数的位数    void reset();           //将整数置为空public:    bool push_back(uchar x);    //从后面插入一位数    bool push_front(uchar x);   //从前面插入一位数    bool pop_back();        //从后面删除一位数public:    uchar& operator[](ulong pos);   //取出pos下标的数字    uchar& operator[](ulong pos)const;public:    bool operator>=(const BigInt &bt)const;    bool operator<(const BigInt &bt)const;    bool operator<=(const BigInt &bt)const;    bool operator>(const BigInt &bt)const;    bool operator==(const BigInt &bt)const;    bool operator!=(const BigInt &bt)const;public:    BigInt& operator++();    BigInt operator++(int);public:    BigInt operator-(const BigInt &bt);    BigInt& operator+=(const BigInt &bt);    BigInt& operator*=(const BigInt &bt);public:    //大整数bt1运算bt2,结果保存在bt中    friend void Add(BigInt &bt, const BigInt &bt1, const BigInt &bt2);    friend void Sub(BigInt &bt, const BigInt &bt1, const BigInt &bt2);    friend void Mul(BigInt &bt, const BigInt &bt1, const BigInt &bt2);    friend void Div(BigInt &bt, const BigInt &bt1, const BigInt &bt2);    friend void Mod(BigInt &bt, const BigInt &bt1, const BigInt &bt2);    friend void Square(BigInt &bt, const BigInt &bt1);    friend void Power(BigInt &bt, const BigInt &bt1, long n);    friend void Power(BigInt &bt, const BigInt &bt1, const BigInt &bt2);private:    SeqList<uchar> big; //用顺序表存放大数};

bigint.cpp

#include "bigint.h"#include <cmath>//Add(),Sub(),Mul()调用的函数,用来计算数的一位的结果uchar AddItem(uchar a, uchar b, uchar &sign);uchar SubItem(uchar a, uchar b, uchar &sign);uchar MulItem(uchar a, uchar b, uchar &sign);BigInt::BigInt(){}BigInt::BigInt(int x){    if (x == 0)    {        push_back(0);        return;    }    while (x > 0)    {        push_back(x % 10);        x /= 10;    }}BigInt& BigInt::operator=(const BigInt &bt){    if (this != &bt)    {        (*this).big = bt.big;    }    return *this;}///////////////////////////////////////////////////////////////void BigInt::LoadData(int sz){//按位数置一个随机数    srand(time(NULL));    for (ulong i = 0; i < sz; i++)    {        push_back(rand() % 10);    }}void BigInt::PrintData()const{//输出数    for (ulong i = size(); i >= 1; i--)    {        cout << (int)big[i];    }    cout << endl;}//////////////////////////////////////////////////////////调用了seqlist的成员函数bool BigInt::push_back(uchar x){    return big.push_back(x);}bool BigInt::push_front(uchar x){    return big.push_front(x);}bool BigInt::pop_back(){    big.pop_back();}void BigInt::reset(){    big.reset();}ulong BigInt::size()const{    return big.Size();}////////////////////////////////////////////////////////uchar& BigInt::operator[](ulong pos){    return big[pos];}uchar& BigInt::operator[](ulong pos)const{    return big[pos];}///////////////////////////////////////////////////////////bool BigInt::operator>=(const BigInt &bt)const{    if (size() > bt.size())        return true;    else if (size() < bt.size())        return false;    ulong i;    i = size();    while (i >= 1)    {        if ((*this)[i] > bt[i])            return true;        else if((*this)[i] < bt[i])            return false;        i--;    }    return true;}bool BigInt::operator<(const BigInt &bt)const{    return !((*this) >= bt);}bool BigInt::operator==(const BigInt &bt)const{    if (size() != bt.size())        return false;    ulong i = size();    while (i >= 1)    {        if ((*this)[i] != bt[i])            return false;        --i;    }    return true;    }bool BigInt::operator!=(const BigInt &bt)const{    return !((*this)==bt);}bool BigInt::operator<=(const BigInt &bt)const{    return ((*this)<bt || (*this)==bt);}//////////////////////////////////////////////////////BigInt& BigInt::operator++(){    ulong i = 1;    uchar sign = 1;    while (sign == 1 && i <= size())    {        (*this)[i] = AddItem((*this)[i], 0, sign);        ++i;    }    if (sign == 1)        push_back(sign);    return *this;}BigInt BigInt::operator++(int){    BigInt tmp = *this;    ++*this;    return tmp;}BigInt& BigInt::operator+=(const BigInt &bt){    ulong i = 1;    ulong j = 1;    uchar sign = 0;    while(i<=size() && j<=bt.size())    {        (*this)[i] = AddItem((*this)[i], bt[j], sign);        ++i;        ++j;    }    while(sign>0 && i<=size())    {//*this没有加完        (*this)[i] = AddItem((*this)[i], 0, sign);        ++i;    }    while(j <= bt.size())    {//bt没有加完的情况,之所以和上一个while循环内部有所不同,     //是为了保证*this的size的正确性        uchar sum = AddItem(0, bt[j], sign);        push_back(sum);        ++j;    }    if(sign > 0)        push_back(sign);    return *this;}BigInt& BigInt::operator*=(const BigInt &bt){    BigInt tmp;    Mul(tmp, (*this), bt);    (*this) = tmp;    return *this;}BigInt BigInt::operator-(const BigInt &bt){    assert(*this >= bt);    BigInt tmp;    Sub(tmp, *this, bt);    return tmp;}///////////////////////////////////////////////////////////void Add(BigInt &bt, const BigInt &bt1, const BigInt &bt2){    bt.reset();    ulong i = 1;    ulong j = 1;    uchar sign = 0;    uchar sum;    while(i<=bt1.size() && j<=bt2.size())    {        sum = AddItem(bt1[i++], bt2[j++], sign);        bt.push_back(sum);    }    while(i <= bt1.size())    {//bt1位数 > bt2位数        sum = AddItem(bt1[i++], 0, sign);        bt.push_back(sum);    }    while(j <= bt2.size())    {//bt2位数 > bt1位数        sum = AddItem(0, bt2[j++], sign);        bt.push_back(sum);    }    if(sign > 0) //最高位的进位        bt.push_back(sign);}void Sub(BigInt &bt, const BigInt &bt1, const BigInt &bt2){    assert(bt1 >= bt2);    bt.reset();    if(bt1 == bt2)    {        bt.push_back(0);        return;    }    ulong i = 1;    ulong j = 1;    uchar sign = 0;    uchar sub;    while(i<=bt1.size() && j<=bt2.size())    {        sub = SubItem(bt1[i++], bt2[j++], sign);        bt.push_back(sub);    }    while(i<=bt1.size())    {        sub = SubItem(bt1[i++], 0, sign);        bt.push_back(sub);    }    for (ulong k = bt.size(); k >= 1; k--)    {//除去前置的0        if (bt[k] == 0)            bt.pop_back();        else            break;    }}#if 0void Mul(BigInt &bt, const BigInt &bt1, const BigInt &bt2){//效率低的版本    for (BigInt i = 0; i < bt2; ++i)    {//bt2个bt1加到bt上        bt += bt1;    }}#endifvoid Mul(BigInt &bt, const BigInt &bt1, const BigInt &bt2){    bt.reset();    if (bt1 == 0 || bt2 == 0)    {//有一个数为0,直接返回0        bt.push_back(0);        return;    }    uchar sign = 0;    for (ulong i = 1; i <= bt2.size(); i++)    {        BigInt mul; //保存bt1和bt2每一位的乘积        for (ulong j = 1; j <= bt1.size(); j++)        {            uchar x = MulItem(bt2[i], bt1[j], sign);            mul.push_back(x);        }        if (sign > 0)        {            mul.push_back(sign);            sign = 0;        }        //bt += mul * pow(10, i-1);        for (ulong k = 1; k < i; k++)            mul.push_front(0); //提升mul        bt += mul;          }}void Div(BigInt &bt, const BigInt &bt1, const BigInt &bt2){    assert(bt2 != 0); //除数不能为0    bt.reset();    if (bt1 < bt2) //若bt1 < bt2, 则返回0    {        bt.push_back(0);        return;    }    BigInt tmp; //被除数    bool on_off = false; //定义一个开关,用于排除前置的0值    for (ulong i = bt1.size(); i >= 1; i--) //从最高位开始    {        tmp.push_front(bt1[i]);        uchar shang = 0; //保存商值        while (tmp >= bt2 && tmp - bt2 >= 0) //1        {            shang++;            //tmp -= bt2;            tmp = tmp - bt2;        }        if (tmp == 0)            tmp.reset();        if (shang != 0)        {            bt.push_front(shang);            on_off = true;        }        else if (shang == 0 && on_off)            bt.push_front(shang);       }}///////////////////////////////////////////////////////////////void Square(BigInt &bt, const BigInt &bt1){//bt ^ 2    Mul(bt, bt1, bt1);}void Power(BigInt &bt, const BigInt &bt1, long n){//bt1 ^ n    if (bt1 == 0)    {        bt = 0;        return;    }    if (n == 0)    {        bt = 1;        return;    }    bt = 1;    for (long i = 0; i < n; i++)    {//n个bt1相乘        bt *= bt1;    }}void Power(BigInt &bt, const BigInt &bt1, const BigInt &bt2){//bt1 ^ bt2    if (bt1 == 0)    {        bt = 0;        return;    }    if (bt2 == 0)    {        bt = 1;        return;    }    bt = 1;    for (BigInt i = 0; i < bt2; ++i)    {//bt2个bt1相乘        bt *= bt1;    }}void Mod(BigInt &bt, const BigInt &bt1, const BigInt &bt2){//bt1 % bt2    if (bt1 <= bt2)    {        bt = 0;        return;    }    BigInt cnt; //bt1中有cnt个bt2    BigInt tmp;    Div(cnt, bt1, bt2);    //bt1减去cnt个bt2, 结果即为余数    Mul(tmp, bt2, cnt);    Sub(bt, bt1, tmp);}///////////////////////////////////////////////////////////////uchar AddItem(uchar a, uchar b, uchar &sign){//计算一位数加法    uchar sum = a + b + sign;#if 0    if (sum >= 10)    {        sum -= 10;        sign = 1;    }    else        sign = 0;#endif    sign = sum / 10;    sum %= 10;    return sum;}uchar SubItem(uchar a, uchar b, uchar &sign){//一位数相减    uchar sub;    if (a - sign >= b)    {//足够减        sub = a - b - sign;        sign = 0;    }    else    {//借位相减        sub = a + 10 - b - sign;        sign = 1;    }    return sub;}uchar MulItem(uchar a, uchar b, uchar &sign){//一位数相乘    uchar mul = a * b + sign;    sign = mul / 10;    mul %= 10;    return mul;}

utili.h

#ifndef __UTILI_H#define __UTILI_H#include <iostream>#include <assert.h>#include <string.h>#include <stdlib.h>using namespace std;typedef  unsigned long ulong;typedef unsigned char  uchar;#endif

Makefile

bigmain : bigmain.o bigint.o        g++ -o bigmain bigmain.o bigint.obigmain.o : bigmain.cpp        g++ -o bigmain.o -c bigmain.cpp -gbigint.o : bigint.cpp        g++ -o bigint.o -c bigint.cpp -g.PHONY:cleanclean:        rm *.o bigmain

测试

  测试很简单,只要定义BigInt对象,并调用友元函数即可.

#include "unistd.h"#include "bigint.h"int main(){        BigInt bt;        BigInt bt1, bt2;        bt1.LoadData(10);        bt1.PrintData();        sleep(1);        bt2.LoadData(10);        bt2.PrintData();        //Add(bt, bt1, bt2);        //Sub(bt, bt1, bt2);        //Mul(bt, bt1, bt2);        //Div(bt, bt1, bt2);        //Square(bt, bt1);        //Power(bt, bt1, 100);        //Power(bt, bt1, bt2);        Mod(bt, bt1, bt2);        bt.PrintData();        return 0;}
0 0
原创粉丝点击