c++之大数 实现加减法

刚开始我见到网上的视频教程里有关于大数的实现,他是使用的链表来存储数值,我开始尝试也使用链表,但是失败了,我又试着使用数组来实现,经过两天的奋战,终于把这个类实现了,但遗憾的是只实现了加减法,因为自己的知识有限,未能实现乘法除法运算,如果有大神知道如何实现,小弟我感激不尽。

直接上代码

#ifndef BIGNUMBER_H  
#define BIGNUMBER_H  
  
#include <iostream>  
#include <string>  
  
class BigNumber  
{  
public:  
    BigNumber();  
    BigNumber(std::string s_16);  
    BigNumber(const BigNumber &number);  
    /************************************************************************/  
    /* 改变数值的操作                                  */  
    /************************************************************************/  
    void setMaxValue();  
    void setMinValue();  
    BigNumber& operator++();//前缀重载  
    const BigNumber operator++(int);//后缀重载  
    BigNumber& operator--();//前缀重载  
    const BigNumber operator--(int);//后缀重载  
    const BigNumber& operator=(const BigNumber &number);  
    const BigNumber& operator+=(const BigNumber &number);  
    const BigNumber& operator-=(const BigNumber &number);  
  
    /************************************************************************/  
    /* 基本运算操作                                   */  
    /************************************************************************/  
    const BigNumber operator+(const BigNumber &number);  
    const BigNumber operator-(const BigNumber &number);  
    const BigNumber operator*(const BigNumber &number);//————————未完成  
    const BigNumber operator/(const BigNumber &number);//————————未完成  
    /************************************************************************/  
    /* 大小比较操作                                           */  
    /************************************************************************/  
    bool operator>(const BigNumber &number);  
    bool operator<(const BigNumber &number);  
    bool operator==(const BigNumber &number);  
    bool operator<=(const BigNumber &number);  
    bool operator>=(const BigNumber &number);  
  
    /************************************************************************/  
    /* 输出操作                                     */  
    /************************************************************************/  
    friend std::ostream& operator<<(std::ostream &os, BigNumber &number);  
    friend std::istream& operator>>(std::istream &is, BigNumber &number);  
  
    const static unsigned int MaxValue = 0xFFFFFFFF;//一个无符号整数的最大值  
    const static unsigned int MinValue = 0x00000000;//一个无符号整数的最小值  
    const static unsigned int Size = 100;//存储区大小  
private:  
    unsigned int data[Size];//存储区  
  
    void _add(unsigned int data[], unsigned int posion);//进位操作  
    void _sub(unsigned int data[], unsigned int posion);//借位操作  
  
    unsigned char toBit4(char c);//字符转数值  
    char fromBit4(unsigned char c);//数值转字符  
  
    void set_Bit16(std::string s_16);  
    std::string get_Bit16();  
};  
  
#endif  
#include "BigNumber.h"  
  
/************************************************************************/  
/* 默认构造函数,初始数值为0                                            */  
/************************************************************************/  
BigNumber::BigNumber()  
{  
    setMinValue();  
}  
/************************************************************************/  
/* 以一个16进制表示的字符串初始化大数                                   */  
/************************************************************************/  
BigNumber::BigNumber(std::string s_16)  
{  
    this->set_Bit16(s_16);  
}  
/************************************************************************/  
/* 拷贝构造函数                                           */  
/************************************************************************/  
BigNumber::BigNumber(const BigNumber &number)  
{  
    for (unsigned int index = 0; index < BigNumber::Size; index++)  
    {  
        this->data[index] = number.data[index];  
    }  
}  
/************************************************************************/  
/* 进位操作实际上是一个自加的过程,如果低位的数值自加后会溢出,则将     */  
/*  高一位的数也自加,否则就直接将当前数值自加后退出        */  
/************************************************************************/  
void BigNumber::_add(unsigned int data[], unsigned int posion)  
{  
    if (this->data[posion] == 0xFFFFFFFF)//如果当前位的值为最大值  
    {  
        if (posion == Size - 1)//如果到达最高位,则直接进行自加,不再进位  
        {  
            this->data[posion]++;  
            return;  
        }  
        _add(data, posion + 1);//通过将高位自加来表示进位  
        this->data[posion]++;  
    }  
    else//若不是最大值则进行自加  
    {  
        this->data[posion]++;  
    }  
}  
  
/************************************************************************/  
/* 借位操作实际上是一个自减的过程,如果低位的数值自减后会溢出,则将     */  
/*  高一位的数也自减,否则就直接将当前数值自减后退出        */  
/************************************************************************/  
void BigNumber::_sub(unsigned int data[], unsigned int posion)  
{  
    if (this->data[posion] == 0x00000000)//如果当前位的值为最小值  
    {  
        if (posion == BigNumber::Size - 1)//如果到达最高位,则直接进行自减,不再借位  
        {  
            this->data[posion]--;  
            return;  
        }  
        _sub(data, posion + 1);//通过将高位自减来表示借位  
        this->data[posion]--;  
    }  
    else//若不是最小值则进行自减  
    {  
        this->data[posion]--;  
    }  
}  
/************************************************************************/  
/* 将一个16进制表示的字符转为数值                                       */  
/************************************************************************/  
unsigned char BigNumber::toBit4(char c)  
{  
    if (c <= '9'&&c >= '0')  
    {  
        return c - '0';  
    }  
    else if (c <= 'F'&&c >= 'A')  
    {  
        return c - 'A' + 10;  
    }  
    else if (c <= 'f'&&c >= 'a')  
    {  
        return c - 'a' + 10;  
    }  
    else  
    {  
        return 0xf0;  
    }  
}  
  
/************************************************************************/  
/* 将一个0~15之内的数值转为16进制表示的字符                             */  
/************************************************************************/  
char BigNumber::fromBit4(unsigned char n)  
{  
    if (n <= 9 && n >= 0)  
    {  
        return n + '0';  
    }  
    if (n<=15&&n>=10)  
    {  
        return n + 'A' - 10;  
    }  
    return '\0';  
}  
  
/************************************************************************/  
/* 将数值转为一个16进制表示的字符串,并返回该字符串                     */  
/************************************************************************/  
std::string BigNumber::get_Bit16()  
{  
    unsigned int index1 = BigNumber::Size - 1;  
    while (this->data[index1] == 0) //指向最高有效位  
    {  
        if (index1 == 0)  
        {  
            break;  
        }  
        index1--;  
    }  
    std::string s_16;  
    for (unsigned int i = index1 +1 ; i > 0;i--)  
    {  
        unsigned char bit7, bit6, bit5, bit4, bit3, bit2, bit1, bit0;  
        unsigned int temp = this->data[i - 1];//取出一个32位  
        /* 
        从高到低得到每一个4bit 
        */  
        bit7 = (temp >> 28) & 0xf;  
        bit6 = (temp >> 24) & 0xf;  
        bit5 = (temp >> 20) & 0xf;  
        bit4 = (temp >> 16) & 0xf;  
        bit3 = (temp >> 12) & 0xf;  
        bit2 = (temp >> 8) & 0xf;  
        bit1 = (temp >> 4) & 0xf;  
        bit0 = temp & 0xf;  
        s_16 += fromBit4(bit7);  
        s_16 += fromBit4(bit6);  
        s_16 += fromBit4(bit5);  
        s_16 += fromBit4(bit4);  
        s_16 += fromBit4(bit3);  
        s_16 += fromBit4(bit2);  
        s_16 += fromBit4(bit1);  
        s_16 += fromBit4(bit0);  
    }  
    return s_16;  
}  
  
/************************************************************************/  
/* 接受一个16进制数的字符串,将其存入转为BigNumber                      */  
/************************************************************************/  
void BigNumber::set_Bit16(std::string s_16)  
{  
    this->setMinValue();//置零  
    unsigned int size = s_16.size();//补位,不够32位则高位补零  
    if (size % 8 == 7)  
    {  
        s_16 = "0" + s_16;  
    }  
    else if (size % 8 == 6)  
    {  
        s_16 = "00" + s_16;  
    }  
    else if (size % 8 == 5)  
    {  
        s_16 = "000" + s_16;  
    }  
    else if (size % 8 == 4)  
    {  
        s_16 = "0000" + s_16;  
    }  
    else if (size % 8 == 3)  
    {  
        s_16 = "00000" + s_16;  
    }  
    else if (size % 8 == 2)  
    {  
        s_16 = "000000" + s_16;  
    }  
    else if (size % 8 == 1)  
    {  
        s_16 = "0000000" + s_16;  
    }  
    /************************************************************************/  
    /* 一次取8个字符,将其转为32位无符号整数存入                            */  
    /************************************************************************/  
    for (unsigned int i = 0; i < s_16.size() / 8; ++i)  
    {  
        std::string c4 = s_16.substr(8 * i, 8 * i + 8);  
        unsigned int bit7, bit6, bit5, bit4, bit3, bit2, bit1, bit0;  
        bit7 = toBit4(c4[0]);  
        bit6 = toBit4(c4[1]);  
        bit5 = toBit4(c4[2]);  
        bit4 = toBit4(c4[3]);  
        bit3 = toBit4(c4[4]);  
        bit2 = toBit4(c4[5]);  
        bit1 = toBit4(c4[6]);  
        bit0 = toBit4(c4[7]);  
        this->data[s_16.size() / 8 - i - 1] |= bit7;  
        this->data[s_16.size() / 8 - i - 1] <<= 4;  
        this->data[s_16.size() / 8 - i - 1] |= bit6;  
        this->data[s_16.size() / 8 - i - 1] <<= 4;  
        this->data[s_16.size() / 8 - i - 1] |= bit5;  
        this->data[s_16.size() / 8 - i - 1] <<= 4;  
        this->data[s_16.size() / 8 - i - 1] |= bit4;  
        this->data[s_16.size() / 8 - i - 1] <<= 4;  
        this->data[s_16.size() / 8 - i - 1] |= bit3;  
        this->data[s_16.size() / 8 - i - 1] <<= 4;  
        this->data[s_16.size() / 8 - i - 1] |= bit2;  
        this->data[s_16.size() / 8 - i - 1] <<= 4;  
        this->data[s_16.size() / 8 - i - 1] |= bit1;  
        this->data[s_16.size() / 8 - i - 1] <<= 4;  
        this->data[s_16.size() / 8 - i - 1] |= bit0;  
    }  
}  
  
/************************************************************************/  
/* 设置数值为最小值                                         */  
/************************************************************************/  
void BigNumber::setMaxValue()  
{  
    for (unsigned int index = 0; index < BigNumber::Size; index++)  
    {  
        data[index] = 0xFFFFFFFF;  
    }  
}  
  
/************************************************************************/  
/* 设置数值为最大值                                         */  
/************************************************************************/  
void BigNumber::setMinValue()  
{  
    for (unsigned int index = 0; index < BigNumber::Size; index++)  
    {  
        data[index] = 0x00000000;  
    }  
}  
  
const BigNumber& BigNumber::operator=(const BigNumber &number)  
{  
    for (unsigned int index = 0; index < BigNumber::Size; index++)  
    {  
        this->data[index] = number.data[index];  
    }  
    return *this;  
}  
  
const BigNumber& BigNumber::operator+=(const BigNumber &number)  
{  
    *this = *this + number;  
    return *this;  
}  
  
const BigNumber& BigNumber::operator-=(const BigNumber &number)  
{  
    *this = *this - number;  
    return *this;  
}  
  
BigNumber& BigNumber::operator++()//前缀重载,返回自加之后的值  
{  
    _add(this->data, 0);  
    return *this;  
}  
  
const BigNumber BigNumber::operator++(int)//后缀重载,返回自加之前的值  
{  
    BigNumber n = *this;  
    _add(this->data, 0);  
    return n;  
}  
  
BigNumber& BigNumber::operator--()//前缀重载,返回自减之后的值  
{  
    _sub(this->data, 0);  
    return *this;  
}  
  
const BigNumber BigNumber::operator--(int)//后缀重载,返回自减之前的值  
{  
    BigNumber n = *this;  
    _sub(this->data, 0);  
    return n;  
}  
  
/******************************************************************************/  
/* 加法操作并不会改变两个操作数本身的值,所以这里保存第一个加数的值到变量n    */  
/* 中,并将最终的和保存到变量n中,返回变量n的值                    */  
/******************************************************************************/  
const BigNumber BigNumber::operator+(const BigNumber &number)  
{  
    BigNumber n = *this;  
    for (unsigned int index = 0; index < BigNumber::Size - 1; ++index)  
    {  
        if (BigNumber::MaxValue - this->data[index] < number.data[index])//如果需要进位则执行进位操作  
        {  
            n._add(n.data, index + 1);  
        }  
        n.data[index] = n.data[index] + number.data[index];//执行加法  
    }  
    n.data[BigNumber::Size - 1] = n.data[BigNumber::Size - 1] + number.data[BigNumber::Size - 1];//最高位不用进行进位  
    return n;  
}  
  
/******************************************************************************/  
/* 减法操作并不会改变两个操作数本身的值,所以这里保存被减数的值到 变量n中     */  
/* 并将最终的差保存到变量n中,返回变量n的值                                  */  
/******************************************************************************/  
const BigNumber BigNumber::operator - (const BigNumber &number)  
{  
    BigNumber n=*this;  
    for (unsigned int index = 0; index < BigNumber::Size - 1; ++index)  
    {  
        if (n.data[index] < number.data[index])//如果不够减,就执行借位操作  
        {  
            n._sub(n.data, index + 1);//借位  
        }  
        n.data[index] = n.data[index] - number.data[index];//执行减法  
    }  
    n.data[BigNumber::Size - 1] = n.data[BigNumber::Size - 1] - number.data[BigNumber::Size - 1];//最高位不需要借位  
    return n;  
}  
  
/************************************************************************/  
/* 比较大小操作                                           */  
/************************************************************************/  
bool BigNumber::operator>(const BigNumber &number)  
{  
    unsigned int index1 = BigNumber::Size - 1;//分别指向最大下标  
    unsigned int index2 = BigNumber::Size - 1;  
    while (this->data[index1] == 0) //指向最高有效位  
    {  
        if (index1 == 0)  
        {  
            break;  
        }  
        index1--;  
    }  
    while (number.data[index2] == 0) //指向最高有效位  
    {  
        if (index2 == 0)  
        {  
            break;  
        }  
        index2--;  
    }  
    if (index1 > index2)  
    {  
        return true;  
    }  
    else if (index1 <index2)  
    {  
        return false;  
    }  
    else//当最高有效位的存储区下标相同时,比较存储区内的数值  
    {  
        if (this->data[index1] > number.data[index2])  
        {  
            return true;  
        }  
        else  
        {  
            return false;  
        }  
    }  
}  
  
bool BigNumber::operator<(const BigNumber &number)  
{  
    unsigned int index1 = BigNumber::Size - 1;//分别指向最大下标  
    unsigned int index2 = BigNumber::Size - 1;  
    while (this->data[index1] == 0) //指向最高有效位  
    {  
        if (index1 == 0)  
        {  
            break;  
        }  
        index1--;  
    }  
    while (number.data[index2] == 0) //指向最高有效位  
    {  
        if (index2 == 0)  
        {  
            break;  
        }  
        index2--;  
    }  
    if (index1 < index2)  
    {  
        return true;  
    }  
    else if (index1 > index2)  
    {  
        return false;  
    }  
    else//当最高有效位的存储区下标相同时,比较存储区内的数值  
    {  
        if (this->data[index1] < number.data[index2])  
        {  
            return true;  
        }  
        else  
        {  
            return false;  
        }  
    }  
}  
  
bool BigNumber::operator == (const BigNumber &number)  
{  
    for (unsigned int index = 0; index < BigNumber::Size; index++)  
    {  
        if (this->data[index] != number.data[index])//只要遇到存储的数值不一样就返回false  
        {  
            return false;  
        }  
    }  
    return true;  
}  
  
bool BigNumber::operator <= (const BigNumber &number)  
{  
    if (*this < number || *this == number)  
    {  
        return true;  
    }  
    return false;  
}  
  
bool BigNumber::operator >= (const BigNumber &number)  
{  
    if (*this > number || *this == number)  
    {  
        return true;  
    }  
    return false;  
}  
  
/************************************************************************/  
/* 重载输出操作,输出一个16进制的字符串,以0x开头                       */  
/************************************************************************/  
std::ostream& operator<<(std::ostream &os, BigNumber &number)  
{  
    std::string s_16;  
    s_16 = number.get_Bit16();  
    os << "0x" << s_16;  
    return os;  
}  
/************************************************************************/  
/* 重载输入操作,接收一个16进制的字符串,不需要0x开头                   */  
/************************************************************************/  
std::istream& operator>>(std::istream &is, BigNumber &number)  
{  
    std::string s_16;  
    is >> s_16;  
    number.set_Bit16(s_16);  
    return is;  
}  

我本来不想使用c++的string来实现数据的输出操作,但发现c++的iostream不能格式化输出数据,所以就暂时使用string来实现数据的显示。在实现类的过程中我也学到了很多知识。

理解了友元函数,友元函数只是在头文件中声明,友元函数并不是类的成员函数,但赋予了友元函数访问类中私有成员的权利,以便多个类实现数据的共享(为了方便使用)

如何更好的以c++的风格重载,以及前缀++和后缀++的区别,了解到为什么前缀++要比后缀++的效率要高,因为前缀++返回的是对象的引用,而后缀++返回的是对象的值。

如果有时间,我会继续查阅资料来实现大数的乘法和除法。

这里贴出我想要实现的大数的内存模型



猜你喜欢

转载自blog.csdn.net/a499957739/article/details/68955401