📄 bigint.h
字号:
/*
无符号大整数类
福州大学数计学院04研究生 彭小聪
04-11-28
高精度*高精度为O(N^2),需要改进,分治法或者fft(傅立叶快速变换);
*/
#ifndef BIG_INT
#define BIG_INT
#include "math.h"
#include <string>
#pragma warning(disable:4035)
typedef unsigned long DWORD;
typedef unsigned int UINT;
typedef unsigned char BYTE;
const DefaultLen = 1;
const MaxLen = 0x1000000;
class CBigInt
{
public:
//构造及析构函数
CBigInt();
CBigInt(DWORD dwValue);
CBigInt(char* pszVal);
CBigInt(CBigInt& x);
virtual ~CBigInt();
public:
//以下定义的是运算
//重载的赋值运算符
CBigInt& operator = (CBigInt& x);
CBigInt& operator = (char* pszVal);
CBigInt& operator = (DWORD dwValue);
//重载的加法运算符
CBigInt& operator += (CBigInt& x);
CBigInt& operator += (DWORD dwValue);
CBigInt operator + (CBigInt& x);
CBigInt operator + (DWORD dwValue);
CBigInt operator ++(); //++a
CBigInt operator ++(int); //a++
//重载的减法运算符,因为是无符号数,所以结果为大数减小数得到的差
CBigInt& operator -= (CBigInt& x);
CBigInt& operator -= (DWORD dwValue);
CBigInt operator - (CBigInt& x);
CBigInt operator - (DWORD dwValue);
CBigInt& operator --(); //--a
CBigInt operator --(int); //a--
//重载的乘法运算符
CBigInt& operator *= (DWORD dwValue);
CBigInt& operator *= (CBigInt& x);
CBigInt operator * (DWORD dwValue);
CBigInt operator * (CBigInt& x);
//重载的除法运算符
DWORD operator /= (DWORD dwValue); //返回余数
CBigInt operator /= (CBigInt& x);//返回余数
CBigInt operator / (DWORD dwValue); //返回商
CBigInt operator / (CBigInt& x);//返回商
CBigInt operator % (CBigInt& x);
DWORD operator % (DWORD dwValue);
//重载的比较运算符
bool operator == (CBigInt& x);
bool operator == (DWORD dwValue);
bool operator != (CBigInt& x);
bool operator != (DWORD dwValue);
bool operator > (CBigInt& x);
bool operator > (DWORD dwValue);
bool operator >= (CBigInt& x);
bool operator >= (DWORD dwValue);
bool operator < (CBigInt& x);
bool operator < (DWORD dwValue);
bool operator <= (CBigInt& x);
bool operator <= (DWORD dwValue);
//乘2运算,即 // a = a * 2^dwTimes; 相当于左移一位二进制,低位补0
CBigInt& Double(DWORD dwTimes = 1);
//除2运算; 相当于右移一位二进制,高位边补0,低位舍弃
CBigInt& Half(DWORD dwTimes = 1);
public:
//以下定义的是常用的操作
//重新分配内存空间,用于增加数据长度,n为新长度
void Expand(DWORD n);
//压缩数据,以节省空间。指去掉高位多余的0。
void Compress();
//转换在十六进制数字符串
void ToHexStr(std::string& s);
std::string ToHexStr();
//转换成十进制数字符串
void ToDecStr(std::string& s);
std::string ToDecStr();
protected:
//辅助函数
inline DWORD LeastOver(DWORD n) ;//查找一个比n大,且为2^x次方的数
protected:
DWORD *pValue; //指向一个DWORD数组,用于存放数值
DWORD len; //DWORD数组的长度
DWORD last; //数组中的有效长度
};
const My_ErrorNo_OverFlow = 0;
const My_ErrorNo_ZeroByDiv = 1;
class CMyException
{
public:
CMyException(char* msg, UINT uErrorNo);
virtual ~CMyException();
char* m_szMsg;
UINT m_uErrorNo;
protected:
CMyException(){}
};
void MemCpy(DWORD* dst, DWORD* src, DWORD n)
{
__asm
{
mov ecx, n;
jecxz to_end;
//保存方向标志
pushf;
mov edi,dst;
mov esi, src;
cmp edi, esi;
jbe to_up; //dst <= src;
mov eax, ecx;
shl eax, 2;
add eax, esi;
cmp edi, eax;
jae to_up; //dst >= src+4n
mov eax, ecx;
dec eax;
shl eax, 2;
add edi, eax;
add esi, eax;
std;
jmp to_mov;
to_up:
cld;
to_mov:
rep movsd;
popf;
to_end:
}
}
CBigInt::CBigInt()
{
pValue = new DWORD[len = DefaultLen];
*pValue = 0;
last = 1;
}
CBigInt::~CBigInt()
{
delete [] pValue;
}
CBigInt::CBigInt(CBigInt &x)
{
pValue = new DWORD[ len = x.len];
memset(&pValue[x.last],0,(len-x.last)*4);
MemCpy(pValue, x.pValue, last = x.last);
}
CBigInt::CBigInt(DWORD dwValue)
{
pValue = new DWORD[ len = DefaultLen];
*pValue = dwValue;
last = 1;
}
CBigInt::CBigInt(char* pszVal)
{
len = DefaultLen;
pValue = new DWORD[len];
operator = (pszVal);
}
void CBigInt::Expand(DWORD n)
{
if (n > MaxLen)
{
CMyException* exception = new CMyException("超过规定能处理的最大整数", My_ErrorNo_OverFlow);
throw exception;
}
if (n > len)
{
DWORD* pTemp = new DWORD [len = n];
memset(&pTemp[last], 0, (n-last)*4);
len = n;
MemCpy(pTemp, pValue, last);
delete [] pValue;
pValue = pTemp;
}
}
CBigInt& CBigInt::operator = (CBigInt& x)
{
if (this != &x)
{
if (len < x.last)
{
Expand(LeastOver(x.last));
}
MemCpy(pValue, x.pValue, last = x.last);
}
return *this;
}
CBigInt& CBigInt::operator = (DWORD dwValue)
{
*pValue = dwValue;
last = 1;
return *this;
}
CBigInt& CBigInt::operator *= (DWORD dwValue)
{
if (dwValue == 0)
{
*pValue = 0;
last = 1;
}
else if (dwValue != 1)
{
DWORD times;
__asm
{
bsr ebx, dwValue;
bsf ecx, dwValue;
cmp ebx, ecx;
jne M0; //如果是2的n次方,则使用移位的乘法
mov times, ebx;
}
return Double(times);
M0:
DWORD dwFull;
__asm
{
mov ebx, this;
mov esi, [ebx]this.pValue;
mov ecx, [ebx]this.last;
mov ebx, dwValue; //乘数
xor edi, edi; //作临时存贮器,保存高位
L1:
mov eax, [esi];
mul ebx;
add eax, edi;
mov [esi], eax;
adc edx, 0;
mov edi, edx;
add esi, 4;
loop L1;
cmp edi, 0;
je L2;
mov dwFull, edi;
}
if (last == len)
{
Expand(LeastOver(last+1));
}
pValue[last++] = dwFull;
}
L2:
return *this;
}
CBigInt& CBigInt::operator *= (CBigInt& x)
{
CBigInt a(*this);
CBigInt result;
a.Expand(LeastOver(x.last + last));
result.Expand(LeastOver(x.last + last+1)); //不用this保存结果是因为考虑到x可能等于*this
for (DWORD i=0; i<x.last; i++)
{
result.operator += (a * x.pValue[i]);
a.Double(32);
}
return *this = result;
}
CBigInt CBigInt::operator * (CBigInt& x)
{
CBigInt a(*this);
return a *= x;
}
CBigInt CBigInt::operator * (DWORD dwValue)
{
CBigInt a(*this);
return a *= dwValue;
}
CBigInt& CBigInt::operator += (DWORD dwValue)
{
__asm
{
mov ebx, this;
mov edi, [ebx]this.pValue;
mov ecx, [ebx]this.last;
mov eax, dwValue;
add [edi], eax;
jnc L3;
mov edx, 1;
jmp L2;
L1:
add dword ptr[edi][edx*4], 1;
jnc L3;
inc edx;
L2:
loop L1;
}
if (last == len)
{
Expand(LeastOver(len+1));
}
pValue[last++] = 1;
L3:
return *this;
}
CBigInt& CBigInt::operator += (CBigInt& x)
{
Expand(x.len);
if(last<x.last)
last=x.last;
__asm
{
mov ebx, this;
mov edi, [ebx]this.pValue;
mov edx, x;
mov esi, [edx]x.pValue;
mov ecx, [edx]x.last;
xor edx, edx;
clc;
L1:
mov eax, [esi][edx*4];
adc [edi][edx*4], eax;
inc edx;
loop L1;
jnc L4;
mov ecx, [ebx]this.last; //如果this的有效位更长,则加进位
mov ebx, x;
sub ecx, [ebx]x.last;
jz L3;
L2:
add [edi][edx*4], 1;
jnc L4;
inc edx;
loop L2;
}
L3:
if (last == len)
{
Expand(LeastOver(len+1));
}
pValue[last++] = 1;
L4:
return *this;
}
CBigInt CBigInt::operator + (DWORD dwValue)
{
CBigInt a(*this);
return a += dwValue;
}
CBigInt CBigInt::operator + (CBigInt& x)
{
CBigInt a(*this);
return a += x;
}
CBigInt& CBigInt::Double(DWORD dwTimes /*= 1*/)
{
if (dwTimes % 32 != 0)
{
DWORD dwFull = 0;
__asm
{
mov ebx, this;
mov edi, [ebx]this.pValue;
mov ebx, [ebx]this.last;
xor eax, eax;
mov ecx, dwTimes;
L1:
mov edx, [edi];
shld [edi], eax, cl;
mov eax, edx;
add edi, 4;
dec ebx;
jnz L1;
neg cl;
shr edx, cl;
jz L2;
mov dwFull, edx;
}
if (len == last)
{
Expand(LeastOver(last+1));
}
pValue[last++] = dwFull;
}
L2:
DWORD dwStep = dwTimes >> 5; //除以32
if (dwStep > 0)
{
Expand(LeastOver(last+dwStep));
MemCpy(&pValue[dwStep], pValue, last);
last += dwStep;
}
return *this;
}
void CBigInt::Compress()
{
DWORD n = LeastOver(last);
if (n < len)
{
DWORD *pTemp = new DWORD [len=n];
MemCpy(pTemp, pValue, last);
delete [] pValue;
pValue = pTemp;
}
}
CBigInt CBigInt::operator ++(int) //a++
{
CBigInt a(*this);
operator += (1);
return a;
}
CBigInt CBigInt::operator ++() //++a
{
return operator += (1);
}
inline DWORD CBigInt::LeastOver(DWORD n)
{
__asm
{
bsr ebx, n;
bsf ecx, n;
cmp ebx, ecx;
je to_set;
inc ebx;
to_set:
xor eax, eax;
bts eax, ebx;
}
}
//////////////////////////////////////////////////////////////////////
// CMyException Class
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CMyException::CMyException(char* msg, UINT uErrorNo)
{
m_szMsg = msg;
m_uErrorNo = uErrorNo;
}
CMyException::~CMyException()
{
}
CBigInt& CBigInt::Half(DWORD dwTimes /*= 1*/)
{
DWORD dwStep = dwTimes / 32;
if (dwStep >= last)
{
*pValue = 0;
last = 1;
return *this;
}
else if (dwStep > 0)
{
MemCpy(pValue, &pValue[dwStep], last-=dwStep);
}
if (dwTimes % 32 != 0)
{
__asm
{
mov ebx, this;
mov edi, [ebx]this.pValue;
mov ebx, [ebx]this.last;
dec ebx;
mov ecx, dwTimes;
xor edx, edx;
L1:
cmp ebx, edx;
je L2;
mov eax, 4[edi][edx*4];
shrd [edi][edx*4], eax, cl;
inc edx;
jmp L1;
L2:
xor eax, eax;
shrd [edi][edx*4], eax, cl;
}
if (last > 1 && pValue[last-1] == 0)
{
last --;
}
}
return *this;
}
CBigInt CBigInt::operator /= (CBigInt& x)//返回余数
{
if (x == 0) //除数为0
{
CMyException* exception = new CMyException("除数为0", My_ErrorNo_ZeroByDiv);
throw exception;
}
if (*this == 0 || x == 1)//被除数为0或除数为1
{
return *this;
}
if (x.last == 1) //除数为DWORD时
{
return operator /= (x.pValue[0]);
}
//商数
CBigInt r;
r.Expand(LeastOver(last-x.last+1));
r.last = last- x.last + 1;
memset(r.pValue, 0, 4*r.len);
//减数数组,分别为x*2^i, (i从0到31),暂时为空,如需要再分配
CBigInt* xx[32];
xx[0] = new CBigInt(x);
for (int i=1; i<32; i++)
{
xx[i] = NULL;
}
//除数高位第一个1的位置(二进制)
DWORD bit_x = x.pValue[x.last-1];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -