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

大整数运算的实现原理

  写一个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 0
void Mul(BigInt &bt, const BigInt &bt1, const BigInt &bt2)
{//效率低的版本
    for (BigInt i = 0; i < bt2; ++i)
    {//bt2个bt1加到bt上
        bt += bt1;
    }
}
#endif
void 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.o
bigmain.o : bigmain.cpp
        g++ -o bigmain.o -c bigmain.cpp -g
bigint.o : bigint.cpp
        g++ -o bigint.o -c bigint.cpp -g
.PHONY:clean
clean:
        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
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值