好了,过了几天终于把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 = temp * BASE + num[i];
ans.num[i] = temp / cnt;
temp %= cnt;
}
ans.clear();
return ans;
}
也没什么大区别,就是temp要是long long,不信改成int试试看就知道了。