小项目之用C++实现以顺序表存储的大数运算

当前手机最多支持9位数的运算,电脑计算器最多支持16位数运算

(1)此程序生成随机数的运算理论上可多至成千上万位

(2)自行输入数据,每个数最大可到unsigned long long的最大值18446744073709551615,支持19位,部分20位数的加减乘除运算

负数运算目前不支持,还在改进中

以顺序表存储大数,0下标先不存储(留作符号位),将数的高位放在高下标,低位放在低下标,(如果数的高位放在顺序表的低下标,进位、对位、借位皆难操作,降低运算效率)输出时将顺序表由高到低位依次输出,即为输入或者求得的大数

代码如下

//utili.h

#pragma once

#include<iostream>
#include<assert.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
using namespace std;

typedef unsigned char u_char;
typedef unsigned long u_long;
typedef unsigned long long u_long_long;

//Seqlist.h
#pragma once

#include"utili.h"

class BigInt;

template<class Type>
class SeqList
{
    friend class BigInt;
public:
	SeqList(size_t sz = DEFAULT_SIZE);
	SeqList(const SeqList<Type> &bt);
	SeqList& operator=(const SeqList<Type> &st);
	~SeqList();
public:
	typedef Type& reference;
	typedef const Type& const_reference;
public:
	void push_back(const Type &x);
	void push_front(const Type &x);
	void pop_back();
	void pop_front();
	reference front();
	reference back();
	void clear();
	const_reference back()const;
	const_reference front()const;
	size_t size()const;
	
public:
	reference operator[](int pos);
	const_reference operator[](int pos)const;
public:
	bool Inc()
	{
		capacity += INC_SIZE;
		Type *new_base = new Type[capacity+1];
		if(NULL == new_base)
		{
			cout<<"Out Of Memory."<<endl;
			//exit(1);
			return false;
		}
		memset(new_base, 0, sizeof(Type)*(capacity+1));
		memcpy(new_base, base, sizeof(Type)*(capacity-INC_SIZE+1));
		delete []base;
		base = new_base;
		return true;
	}
private:
	enum{DEFAULT_SIZE = 10, INC_SIZE = 5};
	Type   *base;
	size_t capacity;
	size_t len;
};
///
template<class Type>
SeqList<Type>::SeqList(size_t sz)
{
	capacity = sz > DEFAULT_SIZE ? sz : DEFAULT_SIZE;
	base = new Type[capacity+1];
	memset(base, 0, sizeof(Type) * (capacity+1));
	len = 0;
}
template<class Type>
SeqList<Type>::SeqList(const SeqList<Type> &bt)
{
	capacity = bt.capacity;
	base = new Type[sizeof(Type)*(capacity+1)];
	memset(base, 0, sizeof(Type)*(capacity+1));
	memcpy(base, bt.base, sizeof(Type)*(bt.len+1));
	len = bt.len;
}
//bt = bt1;
template<class Type>
SeqList<Type>& SeqList<Type>::operator=(const SeqList<Type> &st)
{
	if(this != &st)
	{
		if(capacity < st.len)
		{
			delete []base;
			base = new Type[st.capacity+1];
			capacity = st.capacity;	
		}
		memcpy(base, st.base, sizeof(Type)*(st.len+1));
		len = st.len;
	}
	return *this;
}
template<class Type>
SeqList<Type>::~SeqList()
{
	delete []base;
	base = NULL;
	capacity = len = 0;
}
template<class Type>
void SeqList<Type>::push_back(const Type &x)
{
	//assert(len < capacity);
	if(len>=capacity && !Inc())
		return;

	base[++len] = x;
}
template<class Type>
void SeqList<Type>::push_front(const Type &x)
{
	//assert(len < capacity);
	if(len>=capacity && !Inc())
		return;
	for(int i=++len; i>1; --i)
	{
		base[i] = base[i-1];
	}
	base[1] = x;
}

template<class Type>
void SeqList<Type>::pop_back()
{
	assert(len > 0);
	--len;
}
template<class Type>
void SeqList<Type>::pop_front()
{
	assert(len > 0);
	for(int i=1; i<len; ++i)
	{
		base[i] = base[i+1];
	}
	--len;
}

template<class Type>
typename SeqList<Type>::reference SeqList<Type>::front()
{
	assert(len > 0);
	return base[1];
}
template<class Type>
typename SeqList<Type>::reference SeqList<Type>::back()
{
	assert(len > 0);
	return base[len];
}
template<class Type>
typename SeqList<Type>::const_reference SeqList<Type>::front()const
{
	assert(len > 0);
	return base[1];
}
template<class Type>
typename SeqList<Type>::const_reference SeqList<Type>::back()const
{
	assert(len > 0);
	return base[len];
}
template<class Type>
size_t SeqList<Type>::size()const
{
	return len;
}
template<class Type>
void SeqList<Type>::clear()
{
	len = 0;
}
template<class Type>
typename SeqList<Type>::reference SeqList<Type>::operator[](int pos)
{
	assert(pos>=1 && pos<=len);
	return base[pos];
}
template<class Type>
typename SeqList<Type>::const_reference SeqList<Type>::operator[](int pos)const
{
	assert(pos>=1 && pos<=len);
	return base[pos];
}


//BigInt.h
#pragma once

#include"utili.h"
#include"SeqList.h"

class BigInt;
ostream& operator<<(ostream &out, const BigInt &bt);

class BigInt
{
	friend ostream& operator<<(ostream &out, const BigInt &bt);
public:
	BigInt(u_long_long value = 0);
	BigInt& operator=(u_long value);
public:
	void LoadData(size_t sz);
	void PrintData()const;
public:
	void Clear();
    	void BigIntCopy(char *buf, size_t len, size_t &pos);
public:
	u_char back()const;
	void pop_back();
	size_t size()const;
	void clear();
	void clear_head_zero();
	void push_back(u_char x);
	void push_front(u_char x);
public:
	static u_char AddItem(u_char a, u_char b, u_char &sign);
	static u_char SubItem(u_char a, u_char b, u_char &sign);
	static void   MulItem(BigInt &bt, const BigInt &bt1, u_char x);
	static void   AddMove(BigInt &bt, const BigInt &bt1, int offset);
public:

	static void Add(BigInt &bt, const BigInt &bt1, const BigInt &bt2);
	static void Sub(BigInt &bt, const BigInt &bt1, const BigInt &bt2);
	static void Mul(BigInt &bt, const BigInt &bt1, const BigInt &bt2);
	static void Div(BigInt &bt, const BigInt &bt1, const BigInt &bt2);
    static void Mod(BigInt &bt, const BigInt &bt1, const BigInt &bt2);
	static void Square(BigInt &bt, const BigInt &bt1);//bt = bt1^2;

public:
	u_char& operator[](int pos);
	const u_char& operator[](int pos)const;
public:
	BigInt operator+(const BigInt &bt);
	BigInt operator-(const BigInt &bt);
	BigInt operator*(const BigInt &bt);
	BigInt operator/(const BigInt &bt);
	BigInt operator%(const BigInt &bt);
public:
	BigInt& operator++();
	BigInt operator++(int);
	BigInt& operator--();
	BigInt operator--(int);
public:
	BigInt& operator+=(const BigInt &bt);
	BigInt& operator-=(const BigInt &bt);
	BigInt& operator*=(const BigInt &bt);
	BigInt& operator/=(const BigInt &bt);
	BigInt& operator%=(const BigInt &bt);
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:
	bool operator>(u_long x)const;
	bool operator&(u_long x);
private:
	SeqList<u_char> big;
};

//BigInt.cpp


#include"BigInt.h"

ostream& operator<<(ostream &out, const BigInt &bt)
{
	for(size_t i=bt.size(); i>=1; --i)
	{
		out<<(int)bt[i];
	}
	return out;
}


BigInt::BigInt(u_long_long value)
{
	if(value == 0)
	{
		push_back(0);
	}
	else
	{
		while(value > 0)
		{
			push_back(value % 10);
			value /= 10;
		}
	}
}

//bt = 123
BigInt& BigInt::operator=(u_long value)
{
	(*this).clear();
	if(value == 0)
	{
		push_back(0);
	}
	else
	{
		while(value > 0)
		{
			push_back(value % 10);
			value /= 10;
		}
	}
	return *this;
}
/
void BigInt::LoadData(size_t sz)
{
	clear();
	srand(time(NULL));
	for(int i=0; i<sz; ++i)
	{
		big.push_back(rand()%10);
	}
	clear_head_zero();
}
void BigInt::PrintData()const
{
	for(int i=size(); i>=1; --i)
	{
		cout<<(int)big[i];
	}
	cout<<endl;
}

void BigInt::Clear()
{
    big.clear();
}
void BigInt::BigIntCopy(char *buf, size_t len, size_t &pos)
{
    if(pos == 0)
    {
        memcpy(buf,big.base,1); //copy 0 index
        pos++;
    }
    memcpy(buf,big.base+pos, len);
}

u_char BigInt::back()const
{
	return big.back();
}
void BigInt::pop_back()
{
	big.pop_back();
}
size_t BigInt::size()const
{return big.size();}
void BigInt::clear()
{big.clear();}
void BigInt::push_back(u_char x)
{
	big.push_back(x);
}
void BigInt::push_front(u_char x)
{
	big.push_front(x);
}
void BigInt::clear_head_zero()
{
	while(size()>0 && *this!=0 && (*this).back() == 0)
	{
		pop_back();
	}
}

u_char& BigInt::operator[](int pos)
{return big[pos];}
const u_char& BigInt::operator[](int 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;

	size_t i = size();
	while(i >= 1)
	{
		if((*this)[i] > bt[i])
			return true;
		else if((*this)[i] < bt[i])
			return false;
		--i;
	}
	return false;
}
bool BigInt::operator<=(const BigInt &bt)const
{
	return !(*this > bt);
}
bool BigInt::operator<(const BigInt &bt)const
{
	if(size() < bt.size())
		return true;
	else if(size() > bt.size())
		return false;

	size_t i = size();
	while(i >= 1)
	{
		if((*this)[i] < bt[i])
			return true;
		else if((*this)[i] > bt[i])
			return false;
		--i;
	}
	return false;
}
bool BigInt::operator>=(const BigInt &bt)const
{
	return !(*this < bt);
}
	
bool BigInt::operator==(const BigInt &bt)const
{
	if(size() != bt.size())
		return false;
	size_t i = 1;
	while(i <= size())
	{
		if((*this)[i] != bt[i])
			return false;
		++i;
	}
	return true;

}
bool BigInt::operator!=(const BigInt &bt)const
{
	return !(*this == bt);
}

bool BigInt::operator>(u_long x)const
{
	BigInt tmp(x);
	return *this > tmp;
}

BigInt& BigInt::operator++()
{
	u_char sign = 1;
	size_t i = 1;
	while(sign>0 && i<=size())
	{
		(*this)[i] = AddItem((*this)[i], 0, sign);
		++i;
	}
	if(sign > 0)
		push_back(sign);
	return *this;
}
BigInt BigInt::operator++(int)
{
	BigInt tmp = *this;
	++*this;
	return tmp;
}
BigInt& BigInt::operator--()
{
	assert(*this > 0);
	u_char sign = 1;
	size_t i = 1;
	while(sign>0 && i<=size())
	{
	 	(*this)[i] = SubItem((*this)[i], 0, sign);
		++i;
	}
	clear_head_zero();
	return *this;
}
BigInt BigInt::operator--(int)
{
	BigInt tmp = *this;
	--*this;
	return tmp;
}

BigInt& BigInt::operator+=(const BigInt &bt)
{
	u_char sign = 0;
	size_t i=1, j=1;
	while(i<=size() && j<=bt.size())
	{
		(*this)[i] = AddItem((*this)[i], bt[j], sign);
		++i;
		++j;
	}
	while(sign>0 && i<=size())
	{
		(*this)[i] = AddItem((*this)[i], 0, sign);
		++i;
	}
	while(j <= bt.size())
	{
		u_char sum = AddItem(0, bt[j], sign);
		push_back(sum);
		++j;
	}
	if(sign > 0)
		push_back(sign);
	return *this;

}
BigInt& BigInt::operator-=(const BigInt &bt)
{
	assert(*this >= bt);
	if(*this == bt)
	{
		*this = 0;
		return *this;
	}
	else
	{
		u_char sign = 0;
		size_t i=1, j=1;
		while(i<=size() && j<=bt.size())
		{
			(*this)[i] = SubItem((*this)[i], bt[j], sign);
			++i;
			++j;
		}
		while(sign>0 && i<=size())
		{
			(*this)[i] = SubItem((*this)[i], 0, sign);
			++i;
		}
	}
	return *this;
}
BigInt& BigInt::operator*=(const BigInt &bt)
{
	BigInt tmp;
	BigInt::Mul(tmp, *this, bt);
	*this = tmp;
	return *this;
}
BigInt& BigInt::operator/=(const BigInt &bt)
{
	BigInt tmp;
	BigInt::Div(tmp, *this, bt);
	*this = tmp;
	return *this;
}
BigInt& BigInt::operator%=(const BigInt &bt)
{
	BigInt tmp;
	BigInt::Mod(tmp, *this, bt);
	*this = tmp;
	return *this;
}

BigInt BigInt::operator+(const BigInt &bt)
{
	BigInt tmp;
	BigInt::Add(tmp, *this, bt);
	return tmp;
}
BigInt BigInt::operator-(const BigInt &bt)
{
	BigInt tmp;
	BigInt::Sub(tmp, *this, bt);
	return tmp;
}
BigInt BigInt::operator*(const BigInt &bt)
{
	BigInt tmp;
	BigInt::Mul(tmp, *this, bt);
	return tmp;
}
BigInt BigInt::operator/(const BigInt &bt)
{
	BigInt tmp;
	BigInt::Div(tmp, *this, bt);
	return tmp;
}
BigInt BigInt::operator%(const BigInt &bt)
{
	BigInt tmp;
	BigInt::Mod(tmp, *this, bt);
	return tmp;
}

bool BigInt::operator&(u_long x)
{
	BigInt tmp(2);
	BigInt ans = *this % tmp;
	return ans==1;
}

u_char BigInt::AddItem(u_char a, u_char b, u_char &sign)
{
	u_char sum = a + b + sign;
	if(sum >= 10)
	{
		sum -= 10;
		sign = 1;
	}
	else
		sign = 0;
	return sum;
}
void BigInt::Add(BigInt &bt, const BigInt &bt1, const BigInt &bt2)
{
    bt.clear();
	u_char sum, sign = 0;
	size_t i=1, j=1;
	while(i<=bt1.size() && j<=bt2.size())
	{
		sum = AddItem(bt1[i],bt2[j],sign);
		bt.push_back(sum);
		++i;
		++j;
	}
	while(i <= bt1.size())
	{
		sum = AddItem(bt1[i], 0, sign);
		bt.push_back(sum);
		++i;
	}
	while(j <= bt2.size())
	{
		sum = AddItem(0, bt2[j], sign);
		bt.push_back(sum);
		++j;
	}
	if(sign > 0)
		bt.push_back(sign);
}

u_char BigInt::SubItem(u_char a, u_char b, u_char &sign)
{
	u_char sub;
	if(a >= b+sign)
	{
		sub = a - b - sign;
		sign = 0;
	}
	else
	{
		sub = a + 10 - b - sign;
		sign = 1;
	}
	return sub;
}
void BigInt::Sub(BigInt &bt, const BigInt &bt1, const BigInt &bt2)
{
	bt.clear();
	if(bt1 < bt2)
		return;
	if(bt1 == bt2)
		bt = 0;

	u_char sub, sign = 0;
	size_t i=1, j=1;
	while(i<=bt1.size() && j<=bt2.size())
	{
		sub = SubItem(bt1[i], bt2[j], sign);
		bt.push_back(sub);
		++i;
		++j;
	}
	while(i<=bt1.size())
	{
		sub = SubItem(bt1[i], 0, sign);
		bt.push_back(sub);
		++i;
	}
	bt.clear_head_zero();
}
void BigInt::MulItem(BigInt &bt, const BigInt &bt1, u_char x)
{
	u_char mul, sign = 0;
	size_t i = 1;
	while(i <= bt1.size())
	{
		mul = bt1[i] * x + sign;
		if(mul >= 10)
		{
			sign = mul / 10;
			mul %= 10;
		}
		else
			sign = 0;
		bt.push_back(mul);
		++i;
	}
	if(sign > 0)
		bt.push_back(sign);
}
void BigInt::AddMove(BigInt &bt, const BigInt &bt1, int offset)
{
	u_char sign = 0;
	size_t i = offset;
	size_t j = 1;
	while(i<=bt.size() && j<=bt1.size())
	{
		bt[i] = AddItem(bt[i], bt1[j], sign);
		++i;
		++j;
	}
	while(sign>0 && i<=bt.size())
	{
		bt[i] = AddItem(bt[i], 0, sign);
		++i;
	}
	while(j <= bt1.size())
	{
		u_char sum = AddItem(0, bt1[j], sign);
		bt.push_back(sum);
		++j;
	}
	if(sign > 0)
		bt.push_back(sign);
}
void BigInt::Mul(BigInt &bt, const BigInt &bt1, const BigInt &bt2)
{
	bt.Clear();
	BigInt tmp;
	for(size_t i=1; i<=bt2.size(); ++i)
	{
		tmp.clear();
		MulItem(tmp, bt1, bt2[i]);
		AddMove(bt, tmp, i);
	}
}
void BigInt::Div(BigInt &bt, const BigInt &bt1, const BigInt &bt2)
{
	bt = 0;
	if(bt1 < bt2)
		bt = 0;
	else if(bt1 == bt2)
		bt = 1;
	else
	{
		size_t bt1_len = bt1.size();
		size_t bt2_len = bt2.size();
		int k = bt1_len - bt2_len;

		BigInt btd;
		btd.clear();
		for(size_t i=1; i<=bt2.size(); ++i)
		{
			btd.push_back(bt1[i+k]);
		}
		u_char div = 0;
		while(k >= 0)
		{
			while(btd >= bt2)
			{
				btd -= bt2;
				div++;
				btd.clear_head_zero();
			}
			bt.push_front(div);
			div = 0;

			if(k > 0)
				btd.push_front(bt1[k]);
			--k;
		}
		bt.clear_head_zero();
	}
}
void BigInt::Mod(BigInt &bt, const BigInt &bt1, const BigInt &bt2)
{
	bt = 0;
	if(bt1 < bt2)
		bt = bt1;
	else if(bt1 == bt2)
		bt = 0;
	else
	{
		size_t bt1_len = bt1.size();
		size_t bt2_len = bt2.size();
		int k = bt1_len - bt2_len;

		BigInt btd;
		btd.clear();
		for(size_t i=1; i<=bt2.size(); ++i)
		{
			btd.push_back(bt1[i+k]);
		}

		while(k >= 0)
		{
			while(btd >= bt2)
			{
				btd -= bt2;
				btd.clear_head_zero();
			}

			if(k > 0)
				btd.push_front(bt1[k]);
			--k;
		}
		bt = btd;
		bt.clear_head_zero();
	}
}
void BigInt::Square(BigInt &bt, const BigInt &bt1)
{
	BigInt::Mul(bt, bt1, bt1);
}


验证程序正确性,因为计算器最多只能计算16位数,随机生成了一个16位数和一个15位数

#include<iostream>
#include<windows.h>
#include"BigInt.h"
using namespace std;

void main()
{
	BigInt bt, bt1, bt2;
	bt1.LoadData(16);
	cout<<"bt1 = "<<bt1<<endl;  
	Sleep(1000);
	bt2.LoadData(15);
	cout<<"bt2 = "<<bt2<<endl;  

	BigInt::Add(bt,bt1,bt2);
	cout<<"bt=bt1+bt2= "<<bt<<endl;
	BigInt::Sub(bt,bt1,bt2);
	cout<<"bt=bt1-bt2= "<<bt<<endl;
	BigInt::Mul(bt,bt1,bt2);
	cout<<"bt=bt1*bt2= "<<bt<<endl;
	BigInt::Div(bt,bt1,bt2);
	cout<<"bt=bt1/bt2= "<<bt<<endl;
}

运行结果如下:

计算器算得结果如下:


再来看两个大整数给定值的计算结果,为了展示结果第二个数稍小

#include<iostream>
#include<windows.h>
#include"BigInt.h"
using namespace std;

void main()
{
	
	BigInt bt, bt1(11111111111111111111), bt2(100);
	cout<<"bt1 = "<<bt1<<endl;
	cout<<"bt2 = "<<bt2<<endl;

	BigInt::Add(bt,bt1,bt2);
	cout<<"bt=bt1+bt2= "<<bt<<endl;
	BigInt::Sub(bt,bt1,bt2);
	cout<<"bt=bt1-bt2= "<<bt<<endl;
	BigInt::Mul(bt,bt1,bt2);
	cout<<"bt=bt1*bt2= "<<bt<<endl;
	BigInt::Div(bt,bt1,bt2);
	cout<<"bt=bt1/bt2= "<<bt<<endl;
}


 

后续将会改进程序使之能进行更多运算。


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值