【片段集】大数运算

大数就是很大很大的超出64位整数的表示范围的数。

使用竖式进行加减乘除运算,支持任意位数的整数。暂不支持小数。

上代码。


BigNumber.h

#pragma once
#include <iostream>
using namespace std;
#define DIGITS_OF_BIG_NUMBER 50


class CBigNumber
{
public:
	
	//operators
	friend ostream& operator <<(ostream &cout,CBigNumber& bignumber);
	friend istream& operator >>(istream &cin,CBigNumber& bignumber);
	
	friend bool operator >(CBigNumber &bgn1,CBigNumber &bgn2);
	friend bool operator >=(CBigNumber &bgn1,CBigNumber &bgn2);
	friend bool operator ==(CBigNumber &bgn1,CBigNumber &bgn2);
	friend bool operator <(CBigNumber &bgn1,CBigNumber &bgn2);
	friend bool operator <=(CBigNumber &bgn1,CBigNumber &bgn2);
	
	friend CBigNumber& operator +(CBigNumber &bgn1,CBigNumber &bgn2);
	friend CBigNumber& operator +(int n,CBigNumber &bgn2);
	friend CBigNumber& operator +(CBigNumber &bgn1,int n);
	
	friend CBigNumber& operator -(CBigNumber &bgn1,CBigNumber &bgn2);//没有进行符号处理
	
	friend CBigNumber& operator *(CBigNumber &bgn1,CBigNumber &bgn2);
	 
	friend CBigNumber& operator /(CBigNumber &bgn1,CBigNumber &bgn2);
	
public:
	CBigNumber();
	CBigNumber(char* number);
	CBigNumber(int n);
	CBigNumber(long n);
private:
	char m_cSign;//符号'+' or '-' 【未实现】
	int m_Number[DIGITS_OF_BIG_NUMBER];//存储数据,栈式存储
	int m_nDigits;//记录位数,由于数据是从高到低存储,初始值为DIGITS_OF_BIG_NUMBER,表示没有数位。
};

ostream& operator <<(ostream &cout,CBigNumber& bignumber);
istream& operator >>(istream &cin,CBigNumber& bignumber);

bool operator >(CBigNumber &bgn1,CBigNumber &bgn2);
bool operator >=(CBigNumber &bgn1,CBigNumber &bgn2);
bool operator ==(CBigNumber &bgn1,CBigNumber &bgn2);
bool operator <(CBigNumber &bgn1,CBigNumber &bgn2);
bool operator <=(CBigNumber &bgn1,CBigNumber &bgn2);

CBigNumber& operator +(CBigNumber &bgn1,CBigNumber &bgn2);
CBigNumber& operator +(int n,CBigNumber &bgn2);
CBigNumber& operator +(CBigNumber &bgn1,int n);

CBigNumber& operator -(CBigNumber &bgn1,CBigNumber &bgn2);

CBigNumber& operator *(CBigNumber &bgn1,CBigNumber &bgn2);//bgn1为被乘数,bgn2为乘数

CBigNumber& operator /(CBigNumber &bgn1,CBigNumber &bgn2);bgn1为被除数,bgn2为除数


BigNumber.cpp

#include <iostream>
#include "BigNumber.h"

using namespace std;

CBigNumber::CBigNumber()
{
	m_cSign='+';
	m_nDigits=DIGITS_OF_BIG_NUMBER;
	memset(m_Number,0,DIGITS_OF_BIG_NUMBER*4);
}
CBigNumber::CBigNumber(char* number)
{
	m_nDigits=DIGITS_OF_BIG_NUMBER;
	memset(m_Number,0,DIGITS_OF_BIG_NUMBER*4);
	char c=*number;
	if(c!='-') m_cSign='+';//如果以'-'开头就认为是负数,否则都认为是正数
	else m_cSign='-';
	while(c!='\0')
	{
		if(c>='0'&&c<='9')
		{
			m_nDigits--;
			m_Number[m_nDigits]=c-'0';
			if(m_nDigits==0)
				break;
		}
		number++;
		c=*number;
	}
	//翻转成从低到高的阅读顺序
	int d=(DIGITS_OF_BIG_NUMBER-1-m_nDigits)/2;
	for(int i=0;i<=d;i++)
	{
		char c=m_Number[m_nDigits+i];
		m_Number[m_nDigits+i]=m_Number[DIGITS_OF_BIG_NUMBER-1-i];
		m_Number[DIGITS_OF_BIG_NUMBER-1-i]=c;
	}
}
CBigNumber::CBigNumber(long n)
{
	m_nDigits=DIGITS_OF_BIG_NUMBER;
	memset(m_Number,0,DIGITS_OF_BIG_NUMBER*4);
	while(n>0)//n=0时不用操作,因为BigNumber初始化就是0
	{
		m_nDigits--;
		m_Number[m_nDigits]=n%10;
		n=n/10;
	}
}
CBigNumber::CBigNumber(int n)
{
	m_nDigits=DIGITS_OF_BIG_NUMBER;
	memset(m_Number,0,DIGITS_OF_BIG_NUMBER*4);
	while(n>0)//n=0时不用操作,因为BigNumber初始化就是0
	{
		m_nDigits--;
		m_Number[m_nDigits]=n%10;
		n=n/10;
	}
}
ostream& operator <<(ostream& cout,CBigNumber &bignumber)
{
	if(bignumber.m_nDigits==DIGITS_OF_BIG_NUMBER)
		cout<<0;
	for(int i=bignumber.m_nDigits;i<DIGITS_OF_BIG_NUMBER;i++)
		cout<<bignumber.m_Number[i];
	return cout;
}
istream& operator >>(istream &cin,CBigNumber &bignumber)
{
	char c;
	c=getchar();
	while(c>='0'||c<=9)
	{
		bignumber.m_nDigits--;
		bignumber.m_Number[bignumber.m_nDigits]=c-'0';
		c=getchar();
		if(bignumber.m_nDigits==0) break;
	}
	return cin;
}
bool operator >(CBigNumber &bgn1,CBigNumber &bgn2)
{
	if(bgn1.m_nDigits<bgn2.m_nDigits)//bgn1的位数多
		return true;
	else if(bgn1.m_nDigits>bgn2.m_nDigits)//bgn1的位数少
		return false;
	for(int i=bgn1.m_nDigits;i<DIGITS_OF_BIG_NUMBER;i++)//二者位数相同
	{
		if(bgn1.m_Number[i]>bgn2.m_Number[i])//
		{
			return true;
		}
		else if(bgn1.m_Number[i]<bgn2.m_Number[i])
		{
			return false;
		}
	}
	//执行到这里说明是等于
	return false;
}
bool operator >=(CBigNumber &bgn1,CBigNumber &bgn2)
{
	if(bgn1.m_nDigits<bgn2.m_nDigits)//bgn1的位数多
		return true;
	else if(bgn1.m_nDigits>bgn2.m_nDigits)//bgn1的位数少
		return false;
	for(int i=bgn1.m_nDigits;i<DIGITS_OF_BIG_NUMBER;i++)//二者位数相同
	{
		if(bgn1.m_Number[i]>bgn2.m_Number[i])//
		{
			return true;
		}
		else if(bgn1.m_Number[i]<bgn2.m_Number[i])
		{
			return false;
		}
	}
	//执行到这里说明是等于
	return true;
}
bool operator ==(CBigNumber &bgn1,CBigNumber &bgn2)
{
	if(bgn1.m_nDigits!=bgn2.m_nDigits)//二者位数不相同
		return false;
	for(int i=bgn1.m_nDigits;i<DIGITS_OF_BIG_NUMBER;i++)//二者位数相同
	{
		if(bgn1.m_Number[i]!=bgn2.m_Number[i])
		{
			return false;
		}
	}
	//执行到这里说明是等于
	return true;
}
bool operator <(CBigNumber &bgn1,CBigNumber &bgn2)
{
	if(bgn1.m_nDigits<bgn2.m_nDigits)//bgn1的位数多
		return false;
	else if(bgn1.m_nDigits>bgn2.m_nDigits)//bgn1的位数少
		return true;
	for(int i=bgn1.m_nDigits;i<DIGITS_OF_BIG_NUMBER;i++)//二者位数相同
	{
		if(bgn1.m_Number[i]<bgn2.m_Number[i])//
		{
			return true;
		}
		else if(bgn1.m_Number[i]>bgn2.m_Number[i])
		{
			return false;
		}
	}
	//执行到这里说明是等于
	return false;
}
bool operator <=(CBigNumber &bgn1,CBigNumber &bgn2)
{
	if(bgn1.m_nDigits<bgn2.m_nDigits)//bgn1的位数多
		return false;
	else if(bgn1.m_nDigits>bgn2.m_nDigits)//bgn1的位数少
		return true;
	for(int i=bgn1.m_nDigits;i<DIGITS_OF_BIG_NUMBER;i++)//二者位数相同
	{
		if(bgn1.m_Number[i]<bgn2.m_Number[i])//
		{
			return true;
		}
		else if(bgn1.m_Number[i]>bgn2.m_Number[i])
		{
			return false;
		}
	}
	//执行到这里说明是等于
	return true;
}


CBigNumber& operator +(CBigNumber &bgn1,CBigNumber &bgn2)
{
	static CBigNumber bgnSum;//较大的数作为被加数,和放在较大的数里
	static CBigNumber *pBgnAddend;//较小的数作为加数
	if(bgn1.m_nDigits<bgn2.m_nDigits)
	{
		bgnSum=bgn1;
		pBgnAddend=&bgn2;
	}
	else
	{
		bgnSum=bgn2;
		pBgnAddend=&bgn1;
	}
	
	int carry=0;
	for(int i=DIGITS_OF_BIG_NUMBER-1;i>=bgnSum.m_nDigits;i--)
	{
		carry+=bgnSum.m_Number[i]+pBgnAddend->m_Number[i];
		if(carry>=10)//如果大于10的话向前进位
		{
			bgnSum.m_Number[i]=carry-10;
			carry=1;
		}
		else
		{
			bgnSum.m_Number[i]=carry;
			carry=0;
		}
		if(carry==0&&pBgnAddend->m_nDigits>=i)//加数加完了且没有进位就结束加法
			break;
	}
	//bgnSum.m_nDigits=t;
	if(carry&&bgnSum.m_nDigits>0)//加完了还有进位且不会溢出(被加数加完了),就补上
	{
		bgnSum.m_nDigits--;
		bgnSum.m_Number[bgnSum.m_nDigits]=1;	
	}
	return bgnSum;
}

CBigNumber& operator +(int n,CBigNumber &bgn2)
{
	CBigNumber bgn1(n);
	return bgn1+bgn2;
}
CBigNumber& operator +(CBigNumber &bgn1,int n)
{
	CBigNumber bgn2(n);
	return bgn1+bgn2;
}

CBigNumber& operator -(CBigNumber &bgn1,CBigNumber &bgn2)
{
	static CBigNumber bgnDif;//较大的数作为被减数,差放在被减数中
	static CBigNumber *pBgnSubtractor;//较小的数作为减数
	if(bgn1>bgn2)
	{
		bgnDif=bgn1;
		pBgnSubtractor=&bgn2;
	}
	else
	{
		bgnDif=bgn2;
		pBgnSubtractor=&bgn1;
	}
	int carry=0;
	for(int i=DIGITS_OF_BIG_NUMBER-1;i>=bgnDif.m_nDigits;i--)
	{
		bgnDif.m_Number[i]-=carry;
		carry=0;
		if(bgnDif.m_Number[i]<pBgnSubtractor->m_Number[i])
		{
			carry=1;
			bgnDif.m_Number[i]=bgnDif.m_Number[i]+10-pBgnSubtractor->m_Number[i];
		}
		else
		{
			bgnDif.m_Number[i]=bgnDif.m_Number[i]-pBgnSubtractor->m_Number[i];
		}
		if(carry==0&&pBgnSubtractor->m_nDigits>=i)//如果进位为0且减数减完了就结束
			break;
	}
	//被减数减到头了还没减完,这种情况不存在
	carry=0;
	while(!bgnDif.m_Number[carry]) carry++;//重新计算位数
	bgnDif.m_nDigits=carry;
	
	return bgnDif;
}

CBigNumber& operator *(CBigNumber &bgn1,CBigNumber &bgn2)
{
	static CBigNumber bgnProduct;//积放在这里面
	static CBigNumber *pBgn;
	memset(&bgnProduct,0,sizeof(CBigNumber));
	int carry=0;
	int i,j;
	for(i=DIGITS_OF_BIG_NUMBER-1;i>=bgn2.m_nDigits;i--)//乘数去成被乘数,循环的次数是乘数的位数
	{
		carry=0;
		for(j=DIGITS_OF_BIG_NUMBER-1;j>=bgn1.m_nDigits;j--)//乘以被乘数的每一位
		{
			carry=bgn2.m_Number[i]*bgn1.m_Number[j]+carry+bgnProduct.m_Number[j-(DIGITS_OF_BIG_NUMBER-1-i)];
			if(carry>=10)
			{
				bgnProduct.m_Number[j-(DIGITS_OF_BIG_NUMBER-1-i)]+=carry%10;
				carry/=10;
			}
			else
			{
				bgnProduct.m_Number[j-(DIGITS_OF_BIG_NUMBER-1-i)]=carry;
				carry=0;
			}
		}
		if(carry!=0)//被乘数乘空了还有进位
		{
			bgnProduct.m_Number[j-(DIGITS_OF_BIG_NUMBER-1-i)]=carry;
		}
	}
	i=0;
	while(bgnProduct.m_Number[i]==0) i++;
	bgnProduct.m_nDigits=i;
	return bgnProduct;
}

CBigNumber& operator /(CBigNumber &bgn1,CBigNumber &bgn2)
{
	static CBigNumber bgnQuotient;//商
	static CBigNumber bgnTemp;//除法的中间量
	memset(&bgnQuotient,0,sizeof(CBigNumber));
	memset(&bgnTemp,0,sizeof(CBigNumber));
	bgnQuotient.m_nDigits=DIGITS_OF_BIG_NUMBER;
	if(bgn1<bgn2)//小于的话结果为0
		return bgnQuotient;
	
	int nIndex=bgn1.m_nDigits-1;//当前取到除数的第几位,指向上一次读的位置
	
	//取被除数的前n个数放进temp,n为除数的位数
	for(int i=DIGITS_OF_BIG_NUMBER-bgn2.m_nDigits;i>0;i--)
	{
		nIndex++;
		bgnTemp.m_Number[DIGITS_OF_BIG_NUMBER-i]=bgn1.m_Number[nIndex];
	}
	bgnTemp.m_nDigits=bgn2.m_nDigits;
	//cout<<bgnTemp<<endl;
	
	bgnQuotient.m_nDigits=0;
	while(nIndex<DIGITS_OF_BIG_NUMBER-1)//被除数的所有位都取完结束运算
	{
		//如果temp小于除数,再取一个数放进去
		while(bgnTemp<bgn2&&nIndex<DIGITS_OF_BIG_NUMBER-1)
		{
			for(int i=bgnTemp.m_nDigits;i<DIGITS_OF_BIG_NUMBER;i++)//temp中数据左移
				bgnTemp.m_Number[i-1]=bgnTemp.m_Number[i];

			bgnTemp.m_nDigits--;
			nIndex++;
			bgnTemp.m_Number[DIGITS_OF_BIG_NUMBER-1]=bgn1.m_Number[nIndex];
			bgnQuotient.m_nDigits++;//准备迎接下一个商,如果是继续去数放进temp,那么商中会增加一个0
		}
		
		//计算temp/除数的结果,以及余数放进temp
		while(bgnTemp>=bgn2)
		{
			bgnQuotient.m_Number[bgnQuotient.m_nDigits]++;
			bgnTemp=bgnTemp-bgn2;
			//cout<<"/.."<<bgnTemp<<"\t"<<bgnQuotient.m_Number[bgnQuotient.m_nDigits]<<endl;
		}
	}
	
	//左移
	for(int i=bgnQuotient.m_nDigits;i>=0;i--)
	{
		bgnQuotient.m_Number[DIGITS_OF_BIG_NUMBER-1-bgnQuotient.m_nDigits+i]=bgnQuotient.m_Number[i];
	}
	bgnQuotient.m_nDigits=DIGITS_OF_BIG_NUMBER-1-bgnQuotient.m_nDigits;
	return bgnQuotient;
}


main.cpp

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


int main(int argc, char* argv[])
{
	CBigNumber bignumber1("123456789123456789");
	CBigNumber bignumber2("123456789123456780");
	
	cout<<"条件运算:"<<endl;
	cout<<"> "<<(bignumber1>bignumber2)<<endl;
	cout<<">="<<(bignumber1>=bignumber2)<<endl;
	cout<<"=="<<(bignumber1==bignumber2)<<endl;
	cout<<"< "<<(bignumber1<bignumber2)<<endl;
	cout<<"<="<<(bignumber1<=bignumber2)<<endl;
	
	cout<<"\n四则运算:"<<endl;
	cout<<"+"<<bignumber1+bignumber2<<endl;
	cout<<"-"<<bignumber1-bignumber2<<endl;
	//cout<<"*"<<bignumber1*bignumber2<<endl;
	cout<<"*"<<CBigNumber("123456789")*CBigNumber("123456789")<<endl;
	cout<<"/"<<CBigNumber("78945613")/CBigNumber("123")<<endl;
	
	CBigNumber bgnI("1"),bgnJ("1");double n=1,m=1;
	cout<<1<<'\t'<<bgnI<<"\t\t\t"<<n<<endl;
	cout<<2<<'\t'<<bgnI<<"\t\t\t"<<endl;
	for(int i=2;i<200;i+=2)
	{
		bgnI=bgnI+bgnJ; n=m+n;
		bgnJ=bgnI+bgnJ; m=m+n;
		cout<<i<<'\t'<<bgnI<<"\t\t\t"<<n<<endl;
		cout<<i+1<<'\t'<<bgnJ<<"\t\t\t"<<m<<endl;
	}
	
	return 0;
}








已标记关键词 清除标记
相关推荐
简介 笔者当初为了学习JAVA,收集了很多经典源码,源码难易程度分为初级、中级、高级等,详情看源码列表,需要的可以直接下载! 这些源码反映了那时那景笔者对未来的盲目,对代码的热情、执着,对IT的憧憬、向往!此时此景,笔者只专注Android、Iphone等移动平台开发,看着这些源码心中有万分感慨,写此文章纪念那时那景! Java 源码包 Applet钢琴模拟程序java源码 2个目标文件,提供基本的音乐编辑功能。编辑音乐软件的朋友,这款实例会对你有所帮助。 Calendar万年历 1个目标文件 EJB 模拟银行ATM流程及操作源代码 6个目标文件,EJB来模拟银行ATM机的流程及操作:获取系统属性,初始化JNDI,取得Home对象的引用,创建EJB对象,并将当前的计数器初始化,调用每一个EJB对象的count()方法,保证Bean正常被激活和钝化,EJB对象是用完毕,从内存中清除,从账户中取出amt,如果amt>账户余额抛出异常,一个实体Bean可以表示不同的数据实例,我们应该通过主键来判断删除哪个数据实例…… ejbCreate函数用于初始化一个EJB实例 5个目标文件,演示Address EJB的实现 ,创建一个EJB测试客户端,得到名字上下文,查询jndi名,通过强制转型得到Home接口,getInitialContext()函数返回一个经过初始化的上下文,用client的getHome()函数调用Home接口函数得到远程接口的引用,用远程接口的引用访问EJB。 EJB中JNDI的使用源码例子 1个目标文件,JNDI的使用例子,有源代码,可以下载参考,JNDI的使用,初始化Context,它是连接JNDI树的起始点,查找你要的对象,打印找到的对象,关闭Context…… ftp文件传输 2个目标文件,FTP的目标是:(1)提高文件的共享性(计算机程序和/或数据),(2)鼓励间接地(通过程序)使用远程计算机,(3)保护用户因主机之间的文件存储系统导致的变化,(4)为了可靠和高效地传输,虽然用户可以在终端上直接地使用它,但是它的主要作用是供程序使用的。本规范尝试满足大型主机、微型主机、个人工作站、和TACs 的不同需求。例如,容易实现协议的设计。 Java EJB中有、无状态SessionBean的两个例子 两个例子,无状态SessionBean可会话Bean必须实现SessionBean,获取系统属性,初始化JNDI,取得Home对象的引用,创建EJB对象,计算利息等;在有状态SessionBean中,用累加器,以对话状态存储起来,创建EJB对象,并将当前的计数器初始化,调用每一个EJB对象的count()方法,保证Bean正常被激活和钝化,EJB对象是用完毕,从内存中清除…… Java Socket 聊天通信演示代码 2个目标文件,一个服务器,一个客户端。 Java Telnet客户端实例源码 一个目标文件,演示Socket的使用。 Java 组播组中发送和接受数据实例 3个目标文件。 Java读写文本文件的示例代码 1个目标文件。 java俄罗斯方块 一个目标文件。 Java非对称加密源码实例 1个目标文件 摘要:Java源码,算法相关,非对称加密   Java非对称加密源程序代码实例,本例中使用RSA加密技术,定义加密算法可用 DES,DESede,Blowfish等。   设定字符串为“张三,你好,我是李四”   产生张三的密钥对(keyPairZhang)   张三生成公钥(publicKeyZhang)并发送给李四,这里发送的是公钥的数组字节   通过网络或磁盘等方式,把公钥编码传送给李四,李四接收到张三编码后的公钥,将其解码,李四用张三的公钥加密信息,并发送给李四,张三用自己的私钥解密从李四处收到的信息…… Java利用DES私钥对称加密代码实例 同上 java聊天室 2个目标文件,简单。 java模拟掷骰子2个 1个目标文件,输出演示。 java凭图游戏 一个目标文件,简单。 java求一个整数的因子 如题。 Java生成密钥的实例 1个目标文件 摘要:Java源码,算法相关,密钥   Java生成密钥、保存密钥的实例源码,通过本源码可以了解到Java如何产生单钥加密的密钥(myKey)、产生双钥的密钥对(keyPair)、如何保存公钥的字节数组、保存私钥到文件privateKey.dat、如何用Java对象序列化保存私钥,通常应对私钥加密后再保存、如何从文件中得到公钥编码的字节数组、如何从字节数组解码公钥。 Java数据压缩与传输实例 1个目标文件 摘要:Java源码,文件操作,数据压缩,文件传输   Java数据压缩与传输实例,可以学习一下实例化套按字、得到文件输入流、压缩输入流、文件输出流、实例化缓冲
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页