好了,过了几天终于把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试试看就知道了。