刚开始我见到网上的视频教程里有关于大数的实现,他是使用的链表来存储数值,我开始尝试也使用链表,但是失败了,我又试着使用数组来实现,经过两天的奋战,终于把这个类实现了,但遗憾的是只实现了加减法,因为自己的知识有限,未能实现乘法除法运算,如果有大神知道如何实现,小弟我感激不尽。
直接上代码
//文件BigNumber.h
#ifndef BIGNUMBER_H
#define BIGNUMBER_H
#include
#include
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
//文件BigNumber.cpp
#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 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++的风格重载,以及前缀++和后缀++的区别,了解到为什么前缀++要比后缀++的效率要高,因为前缀++返回的是对象的引用,而后缀++返回的是对象的值。
如果有时间,我会继续查阅资料来实现大数的乘法和除法。这里贴出我想要实现的大数的内存模型