【模板】无符号压位高精度BigInterger
2018-02-28 11:58
405 查看
好了,过了几天终于把BASE从10拓展到了1e8,这样做的意义之一是让运算速度大大加快(尤其是乘法),而且打高精度除以高精度也变得有了意义,我就在这里贴代码,写点注意事项就好了。
首先还是外面的大框架struct BigInterger
{
static const int MAXNUM = 100000;
static const int BASE = 1e8;
static const int BIT = 8;
int num[MAXNUM], len;
BigInterger()
{
memset(num, 0, sizeof num);
len = 0;
}
}可以看到,这里多了两个静态成员变量,BASE是基数,BIT是num数组一个元素的最大位数。
赋值(long long + string) BigInterger operator = (long long temp)
{
len = 0;
do
{
num[++len] = temp % BASE;
temp /= BASE;
}while (temp == 0);
return *this;
}
BigInterger operator = (string &str)
{
len = 0;
int i, j, temp;
for (i = str.size() - 1;i >= BIT;i -= BIT)
{
temp = 0;
for (j = BIT;j >= 1;j--)
temp = temp * 10 + str[i - j + 1] - '0';
num[++len] = temp;
}
temp = 0;
for (j = 0;j <= i;j++)
temp = temp * 10 + str[j] - '0';
num[++len] = temp;
return *this;
}long long版本没什么太大变化,string版本主要是每次拿BIT位(最后一次除外),然后用stringstream把string转换成int。看在stringstream很慢的份上,我把它去掉了。
输入输出(重载<<和>>运算符)istream& operator >> (istream &in, BigInterger &temp)
{
string str;
in >> str;
temp = str;
return in;
}
ostream& operator << (ostream &out, const BigInterger &temp)
{
char buf[BigInterger :: BIT];
sprintf(buf, "%d", temp.num[temp.len]);
out << buf;
for (int i = temp.len - 1;i >= 1;i--)
{
sprintf(buf, "%08d", temp.num[i]);
out << buf;
}
return out;
}可以看出,>>没有多大变化,<<则有些区别,sprintf到buf中,再输出。
去前导0clear void clear()
{
while (num[len] == 0 && len > 1)
len--;
}关系运算符(<老大, 用小于号定义其他关系运算符) bool operator < (const BigInterger &cnt) const
{
if (len != cnt.len) return len < cnt.len;
for (int i = len;i >= 1;i--)
if (num[i] != cnt.num[i])
return num[i] < cnt.num[i];
return false;
}
bool operator > (const BigInterger &cnt) const { return cnt < *this; }
bool operator <= (const BigInterger &cnt) const { return !(cnt < *this); }
bool operator >= (const BigInterger &cnt) const { return !(*this < cnt); }
bool operator != (const BigInterger &cnt) const { return cnt < *this || *this < cnt; }
bool operator == (const BigInterger &cnt) const { return !(cnt < *this) && !(*this < cnt); }
四则运算部分
加 BigInterger operator + (const BigInterger &cnt)
{
BigInterger ans;
for (int i = 1, temp = 0;temp != 0 || i <= len || i <= cnt.len;i++)
{
temp += num[i] + cnt.num[i];
ans.num[++ans.len] = temp % BASE;
temp /= BASE;
}
return ans;
}基本没有变化,不解释了。
减 BigInterger operator - (const BigInterger &cnt)
{
BigInterger ans;
ans.len = len;
for (int i = 0;i <= len;i++)
{
if (num[i] < cnt.num[i])
num[i + 1]--, num[i] += BASE;
ans.num[i] = num[i] - cnt.num[i];
}
ans.clear();
return ans;
}也是基本没有变化,原来的借1当10变成借1当BASE罢了。
乘 BigInterger operator * (const BigInterger &cnt)
{
BigInterger ans;
ans.len = len + cnt.len;
for (int i = 1;i <= len;i++)
{
long long temp = 0;
for (int j = 1;j <= cnt.len || temp != 0;j++)
{
temp += (long long)num[i] * cnt.num[j] + ans.num[i + j - 1];
ans.num[i + j - 1] = temp % BASE;
temp /= BASE;
}
}
ans.clear();
return ans;
}这儿就有些注意点了,首先,temp是long long类型,为什么我也不解释了,可以自己试着把long long改成int看看出了什么事,还有,temp运算时要进行强势类型转换,就是(long long)转换,否则temp结果会自动% INT_MAX,而且系统也不报错,就出了一些很是奇怪的答案。
除(高精度除以单精度) BigInterger operator / (const int &cnt)
{
BigInterger ans;
ans.len = len;
long long temp = 0;
for (int i = len;i >= 1;i--)
{
temp = te
4000
mp * BASE + num[i];
ans.num[i] = temp / cnt;
temp %= cnt;
}
ans.clear();
return ans;
}也没什么大区别,就是temp要是long long,不信改成int试试看就知道了。
首先还是外面的大框架struct BigInterger
{
static const int MAXNUM = 100000;
static const int BASE = 1e8;
static const int BIT = 8;
int num[MAXNUM], len;
BigInterger()
{
memset(num, 0, sizeof num);
len = 0;
}
}可以看到,这里多了两个静态成员变量,BASE是基数,BIT是num数组一个元素的最大位数。
赋值(long long + string) BigInterger operator = (long long temp)
{
len = 0;
do
{
num[++len] = temp % BASE;
temp /= BASE;
}while (temp == 0);
return *this;
}
BigInterger operator = (string &str)
{
len = 0;
int i, j, temp;
for (i = str.size() - 1;i >= BIT;i -= BIT)
{
temp = 0;
for (j = BIT;j >= 1;j--)
temp = temp * 10 + str[i - j + 1] - '0';
num[++len] = temp;
}
temp = 0;
for (j = 0;j <= i;j++)
temp = temp * 10 + str[j] - '0';
num[++len] = temp;
return *this;
}long long版本没什么太大变化,string版本主要是每次拿BIT位(最后一次除外),然后用stringstream把string转换成int。看在stringstream很慢的份上,我把它去掉了。
输入输出(重载<<和>>运算符)istream& operator >> (istream &in, BigInterger &temp)
{
string str;
in >> str;
temp = str;
return in;
}
ostream& operator << (ostream &out, const BigInterger &temp)
{
char buf[BigInterger :: BIT];
sprintf(buf, "%d", temp.num[temp.len]);
out << buf;
for (int i = temp.len - 1;i >= 1;i--)
{
sprintf(buf, "%08d", temp.num[i]);
out << buf;
}
return out;
}可以看出,>>没有多大变化,<<则有些区别,sprintf到buf中,再输出。
去前导0clear void clear()
{
while (num[len] == 0 && len > 1)
len--;
}关系运算符(<老大, 用小于号定义其他关系运算符) bool operator < (const BigInterger &cnt) const
{
if (len != cnt.len) return len < cnt.len;
for (int i = len;i >= 1;i--)
if (num[i] != cnt.num[i])
return num[i] < cnt.num[i];
return false;
}
bool operator > (const BigInterger &cnt) const { return cnt < *this; }
bool operator <= (const BigInterger &cnt) const { return !(cnt < *this); }
bool operator >= (const BigInterger &cnt) const { return !(*this < cnt); }
bool operator != (const BigInterger &cnt) const { return cnt < *this || *this < cnt; }
bool operator == (const BigInterger &cnt) const { return !(cnt < *this) && !(*this < cnt); }
四则运算部分
加 BigInterger operator + (const BigInterger &cnt)
{
BigInterger ans;
for (int i = 1, temp = 0;temp != 0 || i <= len || i <= cnt.len;i++)
{
temp += num[i] + cnt.num[i];
ans.num[++ans.len] = temp % BASE;
temp /= BASE;
}
return ans;
}基本没有变化,不解释了。
减 BigInterger operator - (const BigInterger &cnt)
{
BigInterger ans;
ans.len = len;
for (int i = 0;i <= len;i++)
{
if (num[i] < cnt.num[i])
num[i + 1]--, num[i] += BASE;
ans.num[i] = num[i] - cnt.num[i];
}
ans.clear();
return ans;
}也是基本没有变化,原来的借1当10变成借1当BASE罢了。
乘 BigInterger operator * (const BigInterger &cnt)
{
BigInterger ans;
ans.len = len + cnt.len;
for (int i = 1;i <= len;i++)
{
long long temp = 0;
for (int j = 1;j <= cnt.len || temp != 0;j++)
{
temp += (long long)num[i] * cnt.num[j] + ans.num[i + j - 1];
ans.num[i + j - 1] = temp % BASE;
temp /= BASE;
}
}
ans.clear();
return ans;
}这儿就有些注意点了,首先,temp是long long类型,为什么我也不解释了,可以自己试着把long long改成int看看出了什么事,还有,temp运算时要进行强势类型转换,就是(long long)转换,否则temp结果会自动% INT_MAX,而且系统也不报错,就出了一些很是奇怪的答案。
除(高精度除以单精度) BigInterger operator / (const int &cnt)
{
BigInterger ans;
ans.len = len;
long long temp = 0;
for (int i = len;i >= 1;i--)
{
temp = te
4000
mp * BASE + num[i];
ans.num[i] = temp / cnt;
temp %= cnt;
}
ans.clear();
return ans;
}也没什么大区别,就是temp要是long long,不信改成int试试看就知道了。
相关文章推荐
- 高精度模板(带符号的加减乘除开方/压位)
- 【模板】无符号按位高精度BigInterger
- 高精度模板2(带符号压位加减乘除开方封包)
- 【原创】高精度(压位储存)模板
- 压位高精度模板
- 高精度压位模板
- 【模板】压位高精度
- 『程设解体报告』9的统计(含压位高精度模板)、倒数问题、识别条形码,编程珠玑(含o(n)优化)
- {模板}高精度压位
- 压位高精度模板
- bzoj 2656: [Zjoi2012]数列(sequence)(简单高精度模板2.0)
- 高精度模板
- 初探面向对象编程(1)———高精度模板part1
- 我的高精度除法模板
- 高精度计算模板——棋盘覆盖问题
- 【个人模板】 高精度BigInt
- 【高精度-加减乘除-模板】
- 高精度运算类bign(非负整数)模板
- 高精度模板(大数)
- c++模板分离式编译时无法解析外部符号