以下是我写大数类的头文件,cpp文件,说明文档等,代码可用,但限于笔者自身水平,也有诸多不足之处,有待日后改善。不过程序是没有问题的,可以计算大数的加减乘运算。
readme.md :
程序名:BigNumPlus
程序功能:此程序针对任意整实数的加减乘运算,支持负值的计算。
程序文件: BigNum.h //定义大数类
BigNum.cpp //实现大数的各种运算功能
main.cpp //测试文件
程序的实现思路:
大数存储方式是通过一个int bignum[]数组实现的,数组下标对应数的位数。并增加了
len 和 sign成员表示大数的数值总位数 和 符号位。
程序是通过 成员函数TurnStringtoNum 将string 类型的字符串转化位大数的类型并存储。
整个大数的加减乘运算,是以10进制的逢10进1,不够借1的原则编写的。
程序缺点:
1、没有实现动态的内存分配,造成大量的内存浪费。
2、没有实现除法的运算。
3、没有实现输入输出流的重载。
4、以10进制的形式储存程序好空间大,且效率低。
程序优点:
1、实现了符号支持,即可以负值运算。
2、实现了+、-、*的重载。
3、实现了加减乘的运算。
4、以10进制的形式储存程序,运算思路简单,程序代码好理解。
BigNum.h:
#ifndef BIGNUM_H
#define BIGNUM_H
#include <iostream>
#include<string>
#include<ctype.h>
using namespace std;
#define Max_Size 500 //最大的位数控制
#define Max(a,b) len>b.len?len:b.len//a,b中长度较大的
//此类是大数类,用以实现任意整数之间加减乘的运算
class BigNum
{
public:
BigNum();
virtual ~BigNum();
//此函数是将string类型的数据转换成数组储存
bool TurnStringtoNum(string a);
//赋值运算符重载
BigNum operator=( BigNum other);
//此函数用来判断两个大数绝对值的大小
bool operator>=(BigNum b);
//此函数是实现大数的加法算法
BigNum operator+(BigNum b);
//此函数是实现大数的减法
BigNum operator-(BigNum b);
//此函数是实现大数的乘法
BigNum operator*(BigNum b);
//此函数用来打印大数
void PrintAll();
private:
//定义大数的数据组织方式
int bignum[Max_Size]; //最大控制之内的数值存储方式
int len; //数值长度
char sign; //符号位
};
#endif // BIGNUM_H
BigNum.cpp:
#include "BigNum.h"
//构造函数,初始化各个数据成员
BigNum::BigNum()
{
for(int i=0;i<Max_Size;i++)
{
bignum[i]=0;
}
len=0;
sign='+';//ctor
}
//析构函数
BigNum::~BigNum()
{
//dtor
}
//此函数是将string类型的数据转换成数组储存
bool BigNum::TurnStringtoNum(string a){
//有符号时
if((a[0]=='+')||(a[0]=='-')){
sign=a[0];
for(int i=1;i<(signed)a.size();i++)
{
//判断输入的是否为数值
if(!isdigit(a[i])){
cout<<"对不起,你输入的不是数值"<<endl;
return false;
}
}
for(int i=0;i<Max_Size;i++)bignum[i]=0;
len=a.size()-1;
for(int k=0;k<(signed)a.size()-1;k++)
{
bignum[a.size()-k-2]=a[k+1]-48;//将大数以数组的方式储存,并实现位数与下标对应
}
return true;
}
//无符号时默认符号位为+
else if(isdigit(a[0])){
sign='+';
//判断是否为数值
for(int i=0;i<(signed)a.size();i++)
{
//判断输入的是否为数值
if(!isdigit(a[i])){
cout<<"对不起,你输入的不是数值"<<endl;
return false;
}
}
//字符串转化为大数
for(int i=0;i<Max_Size;i++)bignum[i]=0;
len=a.size();
for(int k=0;k<(signed)a.size();k++)
{
bignum[a.size()-k-1]=a[k]-48;//将大数以数组的方式储存,并实现位数与下标对应
}
return true;
}
//判断符号是否正确
else {cout<<"对不起,你可能+、-号输错了!"<<endl;return false;}
return false;
}
//判断a,b的数值的绝对值的大小
bool BigNum::operator>=(BigNum b){
//当a的长度大于b的长度时
if(len>b.len)return true;
//当a的长度等于b的长度时
else if(len==b.len){
int i=0;
for( i=0;i<len;i++){
if(bignum[len-i-1]==b.bignum[b.len-i-1])continue;
if(bignum[len-i-1]>b.bignum[b.len-i-1])return true;
if(bignum[len-i-1]<b.bignum[b.len-i-1])return false;
}
if(i==len)return true;
}
//当a的长度小于b的长度时
else return false;
return false;
}
//此函数是实现大数的加法算法
BigNum BigNum::operator+(BigNum b){
BigNum result;
//第一种情况
if((sign=='-' && b.sign=='-')||(sign=='+' && b.sign=='+'))
{
if(sign=='-')result.sign='-';
else result.sign='+';
int Msize=Max(a,b);//找到a,b中长度较大的
result.len=Msize+1;//初始化
for(int j=0;j<Msize+1;j++)
{
result.bignum[j]=result.bignum[j]+bignum[j]+b.bignum[j];
//若加和后大于等于10则进位
if(result.bignum[j]>=10)
{
result.bignum[j]=result.bignum[j]-10;
result.bignum[j+1]=result.bignum[j+1]+1;
}
//否则不进
else{
result.bignum[j]=result.bignum[j];
}
}
return result;
}
//第二种情况
if((sign=='-' && b.sign=='+')||(sign=='+' && b.sign=='-'))
{
int Msize=Max(a,b);//找到a,b中长度较大的
result.len=Msize+1;
//分两种情况,1、a>=b 2、a<=b
//1
if((*this)>=b){
result.sign=sign;
for(int j=0;j<Msize+1;j++)
{
result.bignum[j]=result.bignum[j]+bignum[j]-b.bignum[j];
//若减后小于0则需借位
if(result.bignum[j]<0)
{
result.bignum[j]=result.bignum[j]+10;
result.bignum[j+1]=result.bignum[j+1]-1;
}
//否则不借
else{
result.bignum[j]=result.bignum[j];
}
}
}
//2
if(b>=(*this)){
result.sign=b.sign;
for(int j=0;j<Msize+1;j++)
{
result.bignum[j]=result.bignum[j]+b.bignum[j]-bignum[j];
//同上
if(result.bignum[j]<0)
{
result.bignum[j]=result.bignum[j]+10;
result.bignum[j+1]=result.bignum[j+1]-1;
}
else{
result.bignum[j]=result.bignum[j];
}
}
}
return result;
}
return result;
}
//此函数是实现大数的减法
BigNum BigNum::operator-(BigNum b)
{
BigNum result;
//第一种情况
if((sign=='-' && b.sign=='-')||(sign=='+' && b.sign=='+'))
{
int Msize=Max(a,b);//找到a,b中长度较大的
result.len=Msize+1;
if((*this)>=b){
if(sign=='-')result.sign='-';
else result.sign='+';
result.sign=sign;
for(int j=0;j<Msize+1;j++)
{
result.bignum[j]=result.bignum[j]+bignum[j]-b.bignum[j];
if(result.bignum[j]<0)
{
result.bignum[j]=result.bignum[j]+10;
result.bignum[j+1]=result.bignum[j+1]-1;
}
else{
result.bignum[j]=result.bignum[j];
}
}
}
if(b>=(*this)){
if(sign=='-')result.sign='+';
else result.sign='-';
for(int j=0;j<Msize+1;j++)
{
result.bignum[j]=result.bignum[j]+b.bignum[j]-bignum[j];
if(result.bignum[j]<0)
{
result.bignum[j]=result.bignum[j]+10;
result.bignum[j+1]=result.bignum[j+1]-1;
}
else{
result.bignum[j]=result.bignum[j];
}
}
}
return result;
}
//第二种情况
if((sign=='-' && b.sign=='+')||(sign=='+' && b.sign=='-'))
{
if(sign=='-')result.sign='-';
else result.sign='+';
int Msize=Max(a,b);//找到a,b中长度较大的
result.len=Msize+1;//初始化
for(int j=0;j<Msize+1;j++)
{
result.bignum[j]=result.bignum[j]+bignum[j]+b.bignum[j];
if(result.bignum[j]>=10)
{
result.bignum[j]=result.bignum[j]-10;
result.bignum[j+1]=result.bignum[j+1]+1;
}
else{
result.bignum[j]=result.bignum[j];
}
}
return result;
}
return result;
}
//此函数是实现大数的乘法
BigNum BigNum::operator*(BigNum b){
BigNum result;
int Msize=(len+1)*b.len+1;
result.len=Msize;
//同号为正,异号为负
if((sign=='-' && b.sign=='-')||(sign=='+' && b.sign=='+'))result.sign='+';
if((sign=='-' && b.sign=='+')||(sign=='+' && b.sign=='-'))result.sign='-';
int i,j;//循环控制变量
//申请临时空间以存放每层数值
BigNum *temp=new BigNum[b.len];
for(i=0;i<b.len;i++){
for(j=0;j<len;j++){
//b的各个位依次乘以a的值
temp[i].bignum[j+i]=b.bignum[i]*bignum[j]+temp[i].bignum[j+i];
//乘积小与10则不进位
if(temp[i].bignum[j+i]<10){
temp[i].bignum[j+i]=temp[i].bignum[j+i];
}
//否则进位
else {
temp[i].bignum[j+i+1]=temp[i].bignum[j+i]/10;
temp[i].bignum[j+i]=temp[i].bignum[j+i]%10;
}
}
//将每层累加
temp[i].sign=result.sign;
result=result+temp[i];
}
delete temp; //释放内存
return result;
}
//赋值运算符重载
BigNum BigNum::operator= (BigNum other)
{
for(int i=0;i<other.len;i++){
this->bignum[i]=other.bignum[i];
}
this->len=other.len;
this->sign=other.sign;
return *this;
}
//此函数用来打印大数
void BigNum::PrintAll(){
//输出符号位
cout<<sign;
//找到大数前有几个无用的零,并控制其输出
int nu=0;
for(int i=len-1;i>=0;i--)
{
if(bignum[i]==0){nu++;continue;}
else break;
}
if(nu==len)cout<<"0"<<endl;
else{
for(int t=0;t<len-nu;t++){
cout<<bignum[len-t-1-nu];
}
cout<<endl;
}
}
main.cpp:
#include <iostream>
#include"BigNum.h"
using namespace std;
int main()
{
//a,b为操作数值,r为结果数值
BigNum a,b,r;
string A,B;
cout<<"请输入两个任意500位之内的实整数(正负均可):"<<endl;
cin>>A>>B;
if(a.TurnStringtoNum(A)&&b.TurnStringtoNum(B))
{
int order=0;
cout<<"你想让这两个数做什么运算?输入命令前的数字:"<<endl;
cout<<"1、加法"<<endl<<"2、减法"<<endl;
cout<<"3、乘法"<<endl;
cin>>order;
if(order==1)r=a+b;
if(order==2)r=a-b;
if(order==3)r=a*b;
cout<<"结果为:"<<endl;
r.PrintAll();
}
return 0;
}
首先,我们要搞清楚大数的储存方法,我这里是开了一个数组bignum[Max_Size]来存放大数,即从下标0开始,向前存放大数的每一位上的数值,我们知道每一位上的数不可能超过10,所以每位就是0~9,另外还要封装len,表示数值的位数(方便操作),还要符号位sign定义大数的符号正负。TurnStringtoNum函数是将String类型的输入数据转化为大数储存。另外,大数的加法是通过逢10进1的思路实现,减法通过不够10借1实现。代码有注释,不在重复赘述。这里说下乘法,我们知道乘法列竖式计算时,是下面的乘数从个位开始与上面的乘数相乘,且得到的数错位相加得到的。依照这个思路,我们要另外开临时的数组来储存这些需要错位相加的数,具体算法看代码。这里提供几个比较好的博客:
http://blog.csdn.net/hackbuteer1/article/details/6595881
http://blog.csdn.net/dvt777/article/details/48897225
http://blog.csdn.net/snow_5288/article/details/71079692?locationNum=2&fps=1