您的位置:首页 > 编程语言 > C语言/C++

大整数类BIGN的设计与实现 C++高精度模板

2016-11-07 17:00 435 查看
转载自郭大侠的博客点击打开链接

首先感谢刘汝佳所著的《算法竞赛入门经典》。

众所周知,C++中储存能力最大的unsigned long long 也是有着一个上限,如果我们想计算非常大的整数时,就不知所措了,所以,我写了一个高精度类,允许大整数的四则运算

这个类利用字符串进行输入输出,并利用数组进行储存与处理,通过模拟四则运算,可以计算很大的整数的加减乘除比大小。

支持负数,前导零,支持字符串、整型赋值,支持流输入输出

贴上我的代码:

[cpp] view
plain copy

#include<string>

#include<iostream>

#include<iosfwd>

#include<cmath>

#include<cstring>

#include<stdlib.h>

#include<stdio.h>

#include<cstring>

#define MAX_L 2005 //最大长度,可以修改

using namespace std;

class bign

{

public:

int len, s[MAX_L];//数的长度,记录数组

//构造函数

bign();

bign(const char*);

bign(int);

bool sign;//符号 1正数 0负数

string toStr() const;//转化为字符串,主要是便于输出

friend istream& operator>>(istream &,bign &);//重载输入流

friend ostream& operator<<(ostream &,bign &);//重载输出流

//重载复制

bign operator=(const char*);

bign operator=(int);

bign operator=(const string);

//重载各种比较

bool operator>(const bign &) const;

bool operator>=(const bign &) const;

bool operator<(const bign &) const;

bool operator<=(const bign &) const;

bool operator==(const bign &) const;

bool operator!=(const bign &) const;

//重载四则运算

bign operator+(const bign &) const;

bign operator++();

bign operator++(int);

bign operator+=(const bign&);

bign operator-(const bign &) const;

bign operator--();

bign operator--(int);

bign operator-=(const bign&);

bign operator*(const bign &)const;

bign operator*(const int num)const;

bign operator*=(const bign&);

bign operator/(const bign&)const;

bign operator/=(const bign&);

//四则运算的衍生运算

bign operator%(const bign&)const;//取模(余数)

bign factorial()const;//阶乘

bign Sqrt()const;//整数开根(向下取整)

bign pow(const bign&)const;//次方

//一些乱乱的函数

void clean();

~bign();

};

#define max(a,b) a>b ? a : b

#define min(a,b) a<b ? a : b

bign::bign()

{

memset(s, 0, sizeof(s));

len = 1;

sign = 1;

}

bign::bign(const char *num)

{

*this = num;

}

bign::bign(int num)

{

*this = num;

}

string bign::toStr() const

{

string res;

res = "";

for (int i = 0; i < len; i++)

res = (char)(s[i] + '0') + res;

if (res == "")

res = "0";

if (!sign&&res != "0")

res = "-" + res;

return res;

}

istream &operator>>(istream &in, bign &num)

{

string str;

in>>str;

num=str;

return in;

}

ostream &operator<<(ostream &out, bign &num)

{

out<<num.toStr();

return out;

}

bign bign::operator=(const char *num)

{

memset(s, 0, sizeof(s));

char a[MAX_L] = "";

if (num[0] != '-')

strcpy(a, num);

else

for (int i = 1; i < strlen(num); i++)

a[i - 1] = num[i];

sign = !(num[0] == '-');

len = strlen(a);

for (int i = 0; i < strlen(a); i++)

s[i] = a[len - i - 1] - 48;

return *this;

}

bign bign::operator=(int num)

{

if (num < 0)

sign = 0, num = -num;

else

sign = 1;

char temp[MAX_L];

sprintf(temp, "%d", num);

*this = temp;

return *this;

}

bign bign::operator=(const string num)

{

const char *tmp;

tmp = num.c_str();

*this = tmp;

return *this;

}

bool bign::operator<(const bign &num) const

{

if (sign^num.sign)

return num.sign;

if (len != num.len)

return len < num.len;

for (int i = len - 1; i >= 0; i--)

if (s[i] != num.s[i])

return sign ? (s[i] < num.s[i]) : (!(s[i] < num.s[i]));

return !sign;

}

bool bign::operator>(const bign&num)const

{

return num < *this;

}

bool bign::operator<=(const bign&num)const

{

return !(*this>num);

}

bool bign::operator>=(const bign&num)const

{

return !(*this<num);

}

bool bign::operator!=(const bign&num)const

{

return *this > num || *this < num;

}

bool bign::operator==(const bign&num)const

{

return !(num != *this);

}

bign bign::operator+(const bign &num) const

{

if (sign^num.sign)

{

bign tmp = sign ? num : *this;

tmp.sign = 1;

return sign ? *this - tmp : num - tmp;

}

bign result;

result.len = 0;

int temp = 0;

for (int i = 0; temp || i < (max(len, num.len)); i++)

{

int t = s[i] + num.s[i] + temp;

result.s[result.len++] = t % 10;

temp = t / 10;

}

result.sign = sign;

return result;

}

bign bign::operator++()

{

*this = *this + 1;

return *this;

}

bign bign::operator++(int)

{

bign old = *this;

++(*this);

return old;

}

bign bign::operator+=(const bign &num)

{

*this = *this + num;

return *this;

}

bign bign::operator-(const bign &num) const

{

bign b=num,a=*this;

if (!num.sign && !sign)

{

b.sign=1;

a.sign=1;

return b-a;

}

if (!b.sign)

{

b.sign=1;

return a+b;

}

if (!a.sign)

{

a.sign=1;

b=bign(0)-(a+b);

return b;

}

if (a<b)

{

bign c=(b-a);

c.sign=false;

return c;

}

bign result;

result.len = 0;

for (int i = 0, g = 0; i < a.len; i++)

{

int x = a.s[i] - g;

if (i < b.len) x -= b.s[i];

if (x >= 0) g = 0;

else

{

g = 1;

x += 10;

}

result.s[result.len++] = x;

}

result.clean();

return result;

}

bign bign::operator * (const bign &num)const

{

bign result;

result.len = len + num.len;

for (int i = 0; i < len; i++)

for (int j = 0; j < num.len; j++)

result.s[i + j] += s[i] * num.s[j];

for (int i = 0; i < result.len; i++)

{

result.s[i + 1] += result.s[i] / 10;

result.s[i] %= 10;

}

result.clean();

result.sign = !(sign^num.sign);

return result;

}

bign bign::operator*(const int num)const

{

bign x = num;

bign z = *this;

return x*z;

}

bign bign::operator*=(const bign&num)

{

*this = *this * num;

return *this;

}

bign bign::operator /(const bign&num)const

{

bign ans;

ans.len = len - num.len + 1;

if (ans.len < 0)

{

ans.len = 1;

return ans;

}

bign divisor = *this, divid = num;

divisor.sign = divid.sign = 1;

int k = ans.len - 1;

int j = len - 1;

while (k >= 0)

{

while (divisor.s[j] == 0) j--;

if (k > j) k = j;

char z[MAX_L];

memset(z, 0, sizeof(z));

for (int i = j; i >= k; i--)

z[j - i] = divisor.s[i] + '0';

bign dividend = z;

if (dividend < divid) { k--; continue; }

int key = 0;

while (divid*key <= dividend) key++;

key--;

ans.s[k] = key;

bign temp = divid*key;

for (int i = 0; i < k; i++)

temp = temp * 10;

divisor = divisor - temp;

k--;

}

ans.clean();

ans.sign = !(sign^num.sign);

return ans;

}

bign bign::operator/=(const bign&num)

{

*this = *this / num;

return *this;

}

bign bign::operator%(const bign& num)const

{

bign a = *this, b = num;

a.sign = b.sign = 1;

bign result, temp = a / b*b;

result = a - temp;

result.sign = sign;

return result;

}

bign bign::pow(const bign& num)const

{

bign result = 1;

for (bign i = 0; i < num; i++)

result = result*(*this);

return result;

}

bign bign::factorial()const

{

bign result = 1;

for (bign i = 1; i <= *this; i++)

result *= i;

return result;

}

void bign::clean()

{

if (len == 0) len++;

while (len > 1 && s[len - 1] == '\0')

len--;

}

bign bign::Sqrt()const

{

if(*this<0)return -1;

if(*this<=1)return *this;

bign l=0,r=*this,mid;

while(r-l>1)

{

mid=(l+r)/2;

if(mid*mid>*this)

r=mid;

else

l=mid;

}

return l;

}

bign::~bign()

{

}

bign num0,num1,res;

int main()

{

cin>>num0>>num1;

res=num0+num1;

cout<<res<<endl;

num0=5;

num1="71";

res=num0-num1;

cout<<res<<endl;

res=num0.Sqrt();

cout<<res<<endl;

res=num0.pow(5);

cout<<res<<endl;

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: