C++ 实现BigInteger 类
2017-07-01 22:32
483 查看
说明
该文件旨在使 BigInteger 类在 C++ 中能够像基本数据类型一样使用。由于该类是在 vector< int > 类的基础上做计算,所以其计算速度不如 int,但也因此获得了更高的精度。已重载的运算符
运算符类型 | 运算符 |
---|---|
双目运算符 | +(加), -(减), *(乘), /(整除), %(取模) |
关系运算符 | ==(等于), !=(不等于), <(小于), >(大于), <=(小于等于), >=(大于等于) |
逻辑运算符 | ||(逻辑或), &&(逻辑与), !(逻辑非) |
单目运算符 | +(正), -(负) |
自增自减运算符 | ++(自增), –(自减) |
赋值运算符 | =, +=, -=, *=, /=, %= |
位运算符 | >>(右移运算符,与输入流关联), <<(左移运算符,与输出流关联) |
函数声明 | 函数功能 |
---|---|
size_t size() const | 返回 BigInteger 对象的位数 |
BigInteger e(size_t n) const | 返回 BigInteger 对象 ×10n 后的值 |
BigInteger abs() const | 返回 BigInteger 对象的绝对值 |
计算耗时比(tBigIntegertint/longlong)
运算符 | int | long long |
---|---|---|
ostream& operator<<(ostream&, const T&) | 1.087 | 1.097 |
istream& operator>>(istream&, T&) | 1.355 | 1.211 |
abs() | 1.407 | 1.273 |
比较运算符 | 1.490 | 1.506 |
T operator+(const T&, const T&) | 3.180 | 3.063 |
T operator-(const T&, const T&) | 3.140 | 3.014 |
T operator*(const T&, const T&) | 1.938 | 2.121 |
T operator/(const T&, const T&) | 8.698 | 19.616 |
T operator%(const T&, const T&) | 11.038 | 20.656 |
typedef int Type
改为
typedef long long Type
此为第二版本,修复初版以下问题: 1. 缺少 const BigInteger& operator=(int n) 赋值函数导致的程序二义性问题 2. 对于常量 LONG_LONG_MIN abs 为负值的修正 3. 添加输入与构造函数的 const char* 格式检查,格式不符时,当前输入失效,不改变变量值,构造函数则默认构造 BigInteger(0) 该类的局限性: 1. 可以与 bool, int, long long 数据类型做隐式类型转换(只能从低精度往高精度),但不能与浮点数做隐式类型转换 2. 构造函数不支持 long int 类型 3. 对除以 0 错误不做处理
biginteger.h 头文件:
#ifndef BIGINTEGER_H_ #define BIGINTEGER_H_ #include <vector> #include <iostream> #include <cstring> #include <iomanip> #include <string> #include <algorithm> using namespace std; class BigInteger { private: static const int BASE = 100000000; static const int WIDTH = 8; bool sign; size_t length; vector<int> num; void cutLeadingZero(); void setLength(); public: BigInteger(int n = 0); BigInteger(long long n); BigInteger(const char *n); BigInteger(const BigInteger &n); const BigInteger& operator=(int n); const BigInteger& operator=(long long n); const BigInteger& operator=(const char *n); const BigInteger& operator=(const BigInteger &n); size_t size() const; BigInteger e(size_t n) const; BigInteger abs() const; const BigInteger& operator+() const; friend BigInteger operator+(const BigInteger &a, const BigInteger &b); const BigInteger& operator+=(const BigInteger &n); const BigInteger& operator++(); BigInteger operator++(int); BigInteger operator-() const; friend BigInteger operator-(const BigInteger &a, const BigInteger &b); const BigInteger& operator-=(const BigInteger &n); const BigInteger& operator--(); BigInteger operator--(int); friend BigInteger operator*(const BigInteger &a, const BigInteger &b); const BigInteger& operator*=(const BigInteger &n); friend BigInteger operator/(const BigInteger &a, const BigInteger &b); const BigInteger& operator/=(const BigInteger &n); friend BigInteger operator%(const BigInteger &a, const BigInteger &b); const BigInteger& operator%=(const BigInteger &n); friend bool operator<(const BigInteger &a, const BigInteger &b); friend bool operator<=(const BigInteger &a, const BigInteger &b); friend bool operator>(const BigInteger &a, const BigInteger &b); friend bool operator>=(const BigInteger &a, const BigInteger &b); friend bool operator==(const BigInteger &a, const BigInteger &b); friend bool operator!=(const BigInteger &a, const BigInteger &b); friend bool operator||(const BigInteger &a, const BigInteger &b); friend bool operator&&(const BigInteger &a, const BigInteger &b); bool operator!(); friend ostream& operator<<(ostream &out, const BigInteger &n); friend istream& operator>>(istream &in, BigInteger &n); }; #endif // BIGINTEGER_H_
biginteger.cpp 代码实现文件:
#include "biginteger.h" void BigInteger::cutLeadingZero() { while(num.back() == 0 && num.size() != 1) { num.pop_back(); } } void BigInteger::setLength() { cutLeadingZero(); int tmp = num.back(); if(tmp == 0) { length = 1; } else { length = (num.size() - 1) * 8; while(tmp > 0) { ++length; tmp /= 10; } } } BigInteger::BigInteger(int n) { *this = n; } BigInteger::BigInteger(long long n) { *this = n; } BigInteger::BigInteger(const char *n) { *this = n; } BigInteger::BigInteger(const BigInteger &n) { *this = n; } const BigInteger& BigInteger::operator=(int n) { *this = (long long)n; return *this; } const BigInteger& BigInteger::operator=(long long n) { num.clear(); if(n == 0) { num.push_back(0); } if(n >= 0) { sign = true; } else if(n == LONG_LONG_MIN) { *this = "-9223372036854775808"; return *this; } else if(n < 0) { sign = false; n = -n; } while(n != 0) { num.push_back(n % BASE); n /= BASE; } setLength(); return *this; } const BigInteger& BigInteger::operator=(const char *n) { int len = strlen(n); int tmp = 0; int ten = 1; int stop = 0; num.clear(); sign = (n[0] != '-'); if(!sign) { stop = 1; } for(int i = len; i > stop; --i) { tmp += (n[i - 1] - '0') * ten; ten *= 10; if((len - i) % 8 == 7) { num.push_back(tmp); tmp = 0; ten = 1; } } if((len - stop) % WIDTH != 0) { num.push_back(tmp); } setLength(); return *this; } const BigInteger& BigInteger::operator=(const BigInteger &n) { num = n.num; sign = n.sign; length = n.length; return *this; } size_t BigInteger::size() const { return length; } BigInteger BigInteger::e(size_t n) const { int tmp = n % 8; BigInteger ans; ans.length = n + 1; n /= 8; while(ans.num.size() <= n) { ans.num.push_back(0); } ans.num = 1; while(tmp--) { ans.num *= 10; } return ans * (*this); } BigInteger BigInteger::abs() const { BigInteger ans(*this); ans.sign = true; return ans; } const BigInteger& BigInteger::operator+() const { return *this; } BigInteger operator+(const BigInteger &a, const BigInteger &b) { if(!b.sign) { return a - (-b); } if(!a.sign) { return b - (-a); } BigInteger ans; int carry = 0; int aa, bb; size_t lena = a.num.size(); size_t lenb = b.num.size(); size_t len = max(lena, lenb); ans.num.clear(); for(size_t i = 0; i < len; ++i) { if(lena <= i) { aa = 0; } else { aa = a.num[i]; } if(lenb <= i) { bb = 0; } else { bb = b.num[i]; } ans.num.push_back((aa + bb + carry) % BigInteger::BASE); carry = (aa + bb + carry) / BigInteger::BASE; } if(carry > 0) { ans.num.push_back(carry); } ans.setLength(); return ans; } const BigInteger& BigInteger::operator+=(const BigInteger &n) { *this = *this + n; return *this; } const BigInteger& BigInteger::operator++() { *this = *this + 1; return *this; } BigInteger BigInteger::operator++(int) { BigInteger ans(*this); *this = *this + 1; return ans; } BigInteger BigInteger::operator-() const { BigInteger ans(*this); if(ans != 0) { ans.sign = !ans.sign; } return ans; } BigInteger operator-(const BigInteger &a, const BigInteger &b) { if(!b.sign) { return a + (-b); } if(!a.sign) { return -((-a) + b); } if(a < b) { return -(b - a); } BigInteger ans; int carry = 0; int aa, bb; size_t lena = a.num.size(); size_t lenb = b.num.size(); size_t len = max(lena, lenb); ans.num.clear(); for(size_t i = 0; i < len; ++i) { aa = a.num[i]; if(i >= lenb) { bb = 0; } else { bb = b.num[i]; } ans.num.push_back((aa - bb - carry + BigInteger::BASE) % BigInteger::BASE); if(aa < bb + carry) { carry = 1; } else { carry = 0; } } ans.setLength(); return ans; } const BigInteger& BigInteger::operator-=(const BigInteger &n) { *this = *this - n; return *this; } const BigInteger& BigInteger::operator--() { *this = *this - 1; return *this; } BigInteger BigInteger::operator--(int) { BigInteger ans(*this); *this = *this - 1; return ans; } BigInteger operator*(const BigInteger &a, const BigInteger&b) { size_t lena = a.num.size(); size_t lenb = b.num.size(); vector<long long> ansLL; for(size_t i = 0; i < lena; ++i) { for(size_t j = 0; j < lenb; ++j) { if(i + j >= ansLL.size()) { ansLL.push_back((long long)a.num[i] * (long long)b.num[j]); } else { ansLL[i + j] += (long long)a.num[i] * (long long)b.num[j]; } } } while(ansLL.back() == 0 && ansLL.size() != 1) { ansLL.pop_back(); } size_t len = ansLL.size(); long long carry = 0; long long tmp; BigInteger ans; ans.sign = (ansLL.size() == 1 && ansLL[0] == 0) || (a.sign == b.sign); ans.num.clear(); for(size_t i = 0; i < len; ++i) { tmp = ansLL[i]; ans.num.push_back((tmp + carry) % BigInteger::BASE); carry = (tmp + carry) / BigInteger::BASE; } if(carry > 0) { ans.num.push_back(carry); } ans.setLength(); return ans; } const BigInteger& BigInteger::operator*=(const BigInteger &n) { *this = *this * n; return *this; } BigInteger operator/(const BigInteger &a, const BigInteger &b) { BigInteger aa(a.abs()); BigInteger bb(b.abs()); if(aa < bb) { return 0; } char *str = new char[aa.size() + 1]; memset(str, 0, sizeof(char) * (aa.size() + 1)); BigInteger tmp; int lena = aa.length; int lenb = bb.length; for(int i = 0; i <= lena - lenb; ++i) { tmp = bb.e(lena - lenb - i); while(aa >= tmp) { ++str[i]; aa = aa - tmp; } str[i] += '0'; } BigInteger ans(str); delete[]str; ans.sign = (ans == 0 || a.sign == b.sign); return ans; } const BigInteger& BigInteger::operator/=(const BigInteger &n) { *this = *this / n; return *this; } BigInteger operator%(const BigInteger &a, const BigInteger &b) { return a - a / b * b; } const BigInteger& BigInteger::operator%=(const BigInteger &n) { *this = *this - *this / n * n; return *this; } bool operator<(const BigInteger &a, const BigInteger &b) { if(a.sign && !b.sign) { return false; } else if(!a.sign && b.sign) { return true; } else if(a.sign && b.sign) { if(a.length < b.length) { return true; } else if(a.length > b.length) { return false; } else { size_t lena = a.num.size(); for(int i = lena - 1; i >= 0; --i) { if(a.num[i] < b.num[i]) { return true; } else if(a.num[i] > b.num[i]) { return false; } } return false; } } else { return -b < -a; } } bool operator<=(const BigInteger &a, const BigInteger &b) { return !(b < a); } bool operator>(const BigInteger &a, const BigInteger &b) { return b < a; } bool operator>=(const BigInteger &a, const BigInteger &b) { return !(a < b); } bool operator==(const BigInteger &a, const BigInteger &b) { return !(a < b) && !(b < a); } bool operator!=(const BigInteger &a, const BigInteger &b) { return (a < b) || (b < a); } bool operator||(const BigInteger &a, const BigInteger &b) { return a != 0 || b != 0; } bool operator&&(const BigInteger &a, const BigInteger &b) { return a != 0 && b != 0; } bool BigInteger::operator!() { return *this == 0; } ostream& operator<<(ostream &out, const BigInteger &n) { size_t len = n.num.size(); if(!n.sign) { out << '-'; } out << n.num.back(); for(int i = len - 2; i >= 0; --i) { out << setw(BigInteger::WIDTH) << setfill('0') << n.num[i]; } return out; } istream& operator>>(istream &in, BigInteger &n) { string str; in >> str; size_t len = str.length(); size_t i, start = 0; if(str[0] == '-') { start = 1; } if(str[start] == '\0') { return in; } for(i = start; i < len; ++i) { if(str[i] < '0' || str[i] > '9') { return in; } } n = str.c_str(); return in; }
test.cpp 测试文件
#include <iostream> #include <fstream> #include <ctime> #include <cstdlib> #include <cmath> #include <windows.h> #include <climits> #include "biginteger.h" using namespace std; typedef int Type; const int TESTS = 80000; const char typefile[] = "type.txt"; const char bigfile[] = "big.txt"; const Type ZeroType = 0; const BigInteger ZeroBig = 0; Type type[TESTS + 5]; BigInteger big[TESTS + 5]; void Rand(bool half = false, bool Sqrt = false); void Output(); void Input(); void Absolute(); void Compare_Calculate(); int main() { ios::sync_with_stdio(false); srand((unsigned)time(NULL)); Rand(); Output(); Input(); Absolute(); Compare_Calculate(); return 0; } void Rand(bool half, bool Sqrt) { Type tmp; for (int i = 0; i < TESTS; ++i) { do { tmp = ((Type)rand()) << (rand() % (sizeof(Type) * 4)); if(rand() % 2 == 1) { tmp *= ((Type)rand()) << (rand() % (sizeof(Type) * 4)); } if(half) { tmp = abs(tmp / 2) - 1; } if(Sqrt) { if(abs(tmp) < 0) { --tmp; } tmp = sqrt(abs(tmp)) - 1; } if(rand() % 2 == 1) { tmp = -tmp; } } while(tmp == 0); type[i] = tmp; big[i] = tmp; } } void Output() { ofstream fout; int cnt; clock_t start, stop; double time_of_type, time_of_big; fout.open(typefile); cnt = 0; start = clock(); while(cnt != TESTS) { fout << type[cnt++] << endl; } fout << ZeroType << endl; stop = clock(); fout.close(); time_of_type = stop - start; fout.open(bigfile); cnt = 0; start = clock(); while(cnt != TESTS) { fout << big[cnt++] << endl; } fout << ZeroBig << endl; stop = clock(); fout.close(); time_of_big = stop - start; cout << "Output time of type: " << time_of_type << endl << "Output time of big: " << time_of_big << endl << "time_of_big / time_of_type = " << time_of_big / time_of_type << endl << endl; system((string("fc ") + typefile + " " + bigfile).c_str()); } void Input() { ifstream fin; Type typetmp; BigInteger bigtmp; clock_t start, stop; double time_of_type, time_of_big; fin.open(typefile); start = clock(); while(fin >> typetmp); stop = clock(); fin.close(); time_of_type = stop - start; fin.open(bigfile); start = clock(); while(fin >> bigtmp); stop = clock(); fin.close(); time_of_big = stop - start; cout << "Input time of type: " << time_of_type << endl << "Input time of big: " << time_of_big << endl << "time_of_big / time_of_type = " << time_of_big / time_of_type << endl << endl; } void Absolute() { int cnt; ofstream fout; clock_t start, stop; double time_of_type, time_of_big; fout.open(typefile); cnt = 0; start = clock(); while(cnt != TESTS) { if(type[cnt] == LONG_LONG_MIN) { fout << "9223372036854775808" << endl; } else if(type[cnt] == INT_MIN) { fout << "2147483648" << endl; } else { fout << abs(type[cnt]) << endl; } ++cnt; } fout << abs(ZeroType) << endl; stop = clock(); fout.close(); time_of_type = stop - start; fout.open(bigfile); cnt = 0; start = clock(); while(cnt != TESTS) { fout << big[cnt].abs() << endl; ++cnt; } fout << ZeroBig.abs() << endl; stop = clock(); fout.close(); time_of_big = stop - start; cout << "Abs time of type: " << time_of_type << endl << "Abs time of big: " << time_of_big << endl << "time_of_big / time_of_type = " << time_of_big / time_of_type << endl << endl; system((string("fc ") + typefile + " " + bigfile).c_str()); } template<typename T> void cmpcal(T *arr, int command, ofstream &fout) { int cnt; const T ZERO = 0; cnt = 0; while(cnt != TESTS) { switch(command) { case 1: { fout << (arr[cnt] == arr[cnt + 1]) << endl << (arr[cnt] != arr[cnt + 1]) << endl << (arr[cnt] < arr[cnt + 1]) << endl << (arr[cnt] <= arr[cnt + 1]) << endl << (arr[cnt] > arr[cnt + 1]) << endl << (arr[cnt] >= arr[cnt + 1]) << endl; break; } case 2: fout << arr[cnt] / arr[cnt + 1] << endl; break; case 3: fout << arr[cnt] % arr[cnt + 1] << endl; break; case 4: fout << arr[cnt] + arr[cnt + 1] << endl; break; case 5: fout << arr[cnt] - arr[cnt + 1] << endl; break; case 6: fout << arr[cnt] * arr[cnt + 1] << endl; break; default: break; } cnt += 2; } switch(command) { case 2: fout << ZERO / arr[0] << endl; break; case 3: fout << ZERO % arr[0] << endl; break; case 4: fout << ZERO + arr[0] << endl << arr[0] + ZERO << endl; break; case 5: fout << ZERO - arr[0] << endl << arr[0] - ZERO << endl; break; case 6: fout << ZERO * arr[0] << endl << arr[0] * ZERO << endl; break; default: break; } } void Compare_Calculate() { ofstream fout; clock_t start, stop; double time_of_type, time_of_big; string command[6] = {"Compare", "Div", "Mod", "Add", "Cut", "Multiply"}; for(int i = 1; i <= 6; ++i) { switch(i) { case 4: Rand(true, false); break; case 6: Rand(false, true); break; default: break; } fout.open(typefile); start = clock(); cmpcal(type, i, fout); stop = clock(); fout.close(); time_of_type = stop - start; fout.open(bigfile); start = clock(); cmpcal(big, i, fout); stop = clock(); fout.close(); time_of_big = stop - start; cout << command[i - 1] << " time of type: " << time_of_type << endl << command[i - 1] << " time of big: " << time_of_big << endl << "time_of_big / time_of_type = " << time_of_big / time_of_type << endl << endl; system((string("fc ") + typefile + " " + bigfile).c_str()); } }
相关文章推荐
- [中等] 比较完整的BigInteger高精度整数类(C++实现)
- C++ 实现Biginteger
- java.math.BigInteger_100的阶乘的实现
- C++ BigInteger (beta version)
- 剑指offer面试题12 使用BigInteger来实现 打印1到最大的n位数
- 【LeetCode】【Python】【C++】7. Reverse Integer代码实现
- C++ BigInteger 结构体 模板
- 两个好大的数相加,不能用BigInteger来实现
- 手算平方根和基于 Java BigInteger 的大整数平方根的实现
- C++ BigInteger模板
- 有理数类 Java BigInteger实现
- c++ BigInteger模板 非常好的板子
- 用BigInteger实现大素数生成算法
- 【Java BigInteger开方sqrt的实现】
- Java BigInteger求任意n(n∈N*)次方根的实现
- 矩阵取数游戏noip2006(c++ BigInteger的第一次运用)---重点!!
- Silverlight4中利用System.Numerics.BigInteger实现RSA算法
- Java BigInteger 求立方根方法的实现
- java中不用BigInteger实现超大整数的乘法操作
- String to Integer (atoi) C++实现