c++之大数 实现加减法

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

直接上代码

//文件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++的风格重载,以及前缀++和后缀++的区别,了解到为什么前缀++要比后缀++的效率要高,因为前缀++返回的是对象的引用,而后缀++返回的是对象的值。

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

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

c++之大数 实现加减法_第1张图片

你可能感兴趣的:(c++)