[关闭]
@Dmaxiya 2022-04-05T13:39:45.000000Z 字数 18589 阅读 2019

C++ 实现 BigInteger 类

作品


概要

本文提供可复用 C++ BigInteger 类的声明与实现,读者可直接从附录: 源代码一节复制使用或从 Github 上获取代码。笔者希望能提供“像使用基本数据类型一样方便”的高精度整数类,该类具有以下特点:

优点

  1. 内部实现依赖 vector<int> 类型,理论上支持无穷多位高精度整数的计算,上限取决于计算机内存;
  2. 重载大量运算符,支持多种类型构造函数,使用流畅,体验较好;
  3. 基于底层实现提供更高效的基础函数(见“支持的其他函数”一节);
  4. 每 4 字节存 8 个 10 进制位,效率是大多数网上 C++ 高精度整数类实现的 8 倍。

缺点

  1. 未支持位运算符,不能与 int / long long 等基础数据类型无缝切换,涉及到多位位运算建议使用 STL 官方支持的 std::bitset
  2. 计算速度无法与语言原生类型相比,在 __int128 范围内建议使用 C++ 提供的基础数据类型进行计算,不推荐使用 BigInteger 类;
  3. 乘法计算实现未使用速度更快的 FFT 算法实现,存在优化空间;
  4. 更多功能局限性见其他说明

已重载运算符

BigInteger 类重载了除位运算外所有与整数计算相关的运算符,目前已重载运算符如下表:

运算符类型 运算符
双目运算符 + (加), - (减), * (乘), / (整除), % (取模)
关系运算符 == (等于), != (不等于), < (小于), > (大于), <= (小于等于), >=(大于等于)
逻辑运算符 || (逻辑或), && (逻辑与), ! (逻辑非)
单目运算符 + (正), - (负)
自增自减运算符 ++ (自增), -- (自减)
赋值运算符 =, +=, -=, *=, /=, %=
位运算符 >> (右移运算符,与输入流关联), << (左移运算符,与输出流关联)

使用方式见附录: 重载运算符

支持的其他函数

在使用 vector<int> 作为底层数据结构存储的情况下,BigInteger 类针对某些特殊场景提供了更高效的成员函数供外部调用:

函数声明 函数功能
size_t size() const 返回 BigInteger 的十进制位数
BigInteger e(size_t n) const 返回 BigInteger 对象 后的值
BigInteger abs() const 返回 BigInteger 对象的绝对值

使用方式见附录: 其他函数,更多函数请使用者在已有代码基础上自行编写。

运行性能

为了评测 BigInteger 类的性能,这里将 BigIntger 类与基本数据类型 int / long long 的计算速度进行对比,随机生成 80000 组数据,计算得到 BigInteger 类与基本数据类型进行 80000 次相同计算的耗时比:(),部分基础能力评测结果如下表:

运算 int long long
ostream& operator<<(ostream&, const T&) 1.0628 1.05479
istream& operator>>(istream&, T&) 1.63793 1.47059
abs() 1.2542 1.28082
比较运算符 1.36558 1.33571
T operator+(const T&, const T&) 2.68966 2.55204
T operator-(const T&, const T&) 2.48848 2.59545
T operator*(const T&, const T&) 1.7549 1.89862
T operator/(const T&, const T&) 6.4381 15.0192
T operator%(const T&, const T&) 8.70732 15.9469

检验结果准确性与运行时间代码见附录: 性能测试。默认将 BigInteger 类的计算时间与 int 类型数据计算时间比较,若要与 long long 类型计算时间进行比较,可将程序中

  1. typedef int Type

  改为

  1. 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 头文件:

  1. #ifndef BIGINTEGER_H_
  2. #define BIGINTEGER_H_
  3. #include <vector>
  4. #include <iostream>
  5. #include <cstring>
  6. #include <iomanip>
  7. using namespace std;
  8. class BigInteger {
  9. private:
  10. static const int BASE = 100000000;
  11. static const int WIDTH = 8;
  12. bool sign;
  13. size_t length;
  14. vector<int> num;
  15. void cutLeadingZero();
  16. void setLength();
  17. public:
  18. static const long long LONG_LONG_MIN = 1LL << 63;
  19. BigInteger(int n = 0);
  20. BigInteger(long long n);
  21. BigInteger(const char *n);
  22. BigInteger(const BigInteger &n);
  23. const BigInteger& operator=(int n);
  24. const BigInteger& operator=(long long n);
  25. const BigInteger& operator=(const char *n);
  26. const BigInteger& operator=(const BigInteger &n);
  27. size_t size() const;
  28. BigInteger e(size_t n) const;
  29. BigInteger abs() const;
  30. const BigInteger& operator+() const;
  31. friend BigInteger operator+(const BigInteger &a, const BigInteger &b);
  32. const BigInteger& operator+=(const BigInteger &n);
  33. const BigInteger& operator++();
  34. BigInteger operator++(int);
  35. BigInteger operator-() const;
  36. friend BigInteger operator-(const BigInteger &a, const BigInteger &b);
  37. const BigInteger& operator-=(const BigInteger &n);
  38. const BigInteger& operator--();
  39. BigInteger operator--(int);
  40. friend BigInteger operator*(const BigInteger &a, const BigInteger &b);
  41. const BigInteger& operator*=(const BigInteger &n);
  42. friend BigInteger operator/(const BigInteger &a, const BigInteger &b);
  43. const BigInteger& operator/=(const BigInteger &n);
  44. friend BigInteger operator%(const BigInteger &a, const BigInteger &b);
  45. const BigInteger& operator%=(const BigInteger &n);
  46. friend bool operator<(const BigInteger &a, const BigInteger &b);
  47. friend bool operator<=(const BigInteger &a, const BigInteger &b);
  48. friend bool operator>(const BigInteger &a, const BigInteger &b);
  49. friend bool operator>=(const BigInteger &a, const BigInteger &b);
  50. friend bool operator==(const BigInteger &a, const BigInteger &b);
  51. friend bool operator!=(const BigInteger &a, const BigInteger &b);
  52. friend bool operator||(const BigInteger &a, const BigInteger &b);
  53. friend bool operator&&(const BigInteger &a, const BigInteger &b);
  54. bool operator!();
  55. friend ostream& operator<<(ostream &out, const BigInteger &n);
  56. friend istream& operator>>(istream &in, BigInteger &n);
  57. };
  58. #endif // BIGINTEGER_H_

biginteger.cpp 文件:

  1. #include "biginteger.h"
  2. void BigInteger::cutLeadingZero() {
  3. while(num.back() == 0 && num.size() != 1) {
  4. num.pop_back();
  5. }
  6. }
  7. void BigInteger::setLength() {
  8. cutLeadingZero();
  9. int tmp = num.back();
  10. if(tmp == 0) {
  11. length = 1;
  12. } else {
  13. length = (num.size() - 1) * 8;
  14. while(tmp > 0) {
  15. ++length;
  16. tmp /= 10;
  17. }
  18. }
  19. }
  20. BigInteger::BigInteger(int n) {
  21. *this = n;
  22. }
  23. BigInteger::BigInteger(long long n) {
  24. *this = n;
  25. }
  26. BigInteger::BigInteger(const char *n) {
  27. *this = n;
  28. }
  29. BigInteger::BigInteger(const BigInteger &n) {
  30. *this = n;
  31. }
  32. const BigInteger& BigInteger::operator=(int n) {
  33. *this = (long long)n;
  34. return *this;
  35. }
  36. const BigInteger& BigInteger::operator=(long long n) {
  37. num.clear();
  38. if(n == 0) {
  39. num.push_back(0);
  40. }
  41. if(n >= 0) {
  42. sign = true;
  43. } else if(n == LONG_LONG_MIN) {
  44. *this = "-9223372036854775808";
  45. return *this;
  46. } else if(n < 0) {
  47. sign = false;
  48. n = -n;
  49. }
  50. while(n != 0) {
  51. num.push_back(n % BASE);
  52. n /= BASE;
  53. }
  54. setLength();
  55. return *this;
  56. }
  57. const BigInteger& BigInteger::operator=(const char *n) {
  58. int len = strlen(n);
  59. int tmp = 0;
  60. int ten = 1;
  61. int stop = 0;
  62. num.clear();
  63. sign = (n[0] != '-');
  64. if(!sign) {
  65. stop = 1;
  66. }
  67. for(int i = len; i > stop; --i) {
  68. tmp += (n[i - 1] - '0') * ten;
  69. ten *= 10;
  70. if((len - i) % 8 == 7) {
  71. num.push_back(tmp);
  72. tmp = 0;
  73. ten = 1;
  74. }
  75. }
  76. if((len - stop) % WIDTH != 0) {
  77. num.push_back(tmp);
  78. }
  79. setLength();
  80. return *this;
  81. }
  82. const BigInteger& BigInteger::operator=(const BigInteger &n) {
  83. num = n.num;
  84. sign = n.sign;
  85. length = n.length;
  86. return *this;
  87. }
  88. size_t BigInteger::size() const {
  89. return length;
  90. }
  91. BigInteger BigInteger::e(size_t n) const {
  92. int tmp = n % 8;
  93. BigInteger ans;
  94. ans.length = n + 1;
  95. n /= 8;
  96. while(ans.num.size() <= n) {
  97. ans.num.push_back(0);
  98. }
  99. ans.num[n] = 1;
  100. while(tmp--) {
  101. ans.num[n] *= 10;
  102. }
  103. return ans * (*this);
  104. }
  105. BigInteger BigInteger::abs() const {
  106. BigInteger ans(*this);
  107. ans.sign = true;
  108. return ans;
  109. }
  110. const BigInteger& BigInteger::operator+() const {
  111. return *this;
  112. }
  113. BigInteger operator+(const BigInteger &a, const BigInteger &b) {
  114. if(!b.sign) {
  115. return a - (-b);
  116. }
  117. if(!a.sign) {
  118. return b - (-a);
  119. }
  120. BigInteger ans;
  121. int carry = 0;
  122. int aa, bb;
  123. size_t lena = a.num.size();
  124. size_t lenb = b.num.size();
  125. size_t len = max(lena, lenb);
  126. ans.num.clear();
  127. for(size_t i = 0; i < len; ++i) {
  128. if(lena <= i) {
  129. aa = 0;
  130. } else {
  131. aa = a.num[i];
  132. }
  133. if(lenb <= i) {
  134. bb = 0;
  135. } else {
  136. bb = b.num[i];
  137. }
  138. ans.num.push_back((aa + bb + carry) % BigInteger::BASE);
  139. carry = (aa + bb + carry) / BigInteger::BASE;
  140. }
  141. if(carry > 0) {
  142. ans.num.push_back(carry);
  143. }
  144. ans.setLength();
  145. return ans;
  146. }
  147. const BigInteger& BigInteger::operator+=(const BigInteger &n) {
  148. *this = *this + n;
  149. return *this;
  150. }
  151. const BigInteger& BigInteger::operator++() {
  152. *this = *this + 1;
  153. return *this;
  154. }
  155. BigInteger BigInteger::operator++(int) {
  156. BigInteger ans(*this);
  157. *this = *this + 1;
  158. return ans;
  159. }
  160. BigInteger BigInteger::operator-() const {
  161. BigInteger ans(*this);
  162. if(ans != 0) {
  163. ans.sign = !ans.sign;
  164. }
  165. return ans;
  166. }
  167. BigInteger operator-(const BigInteger &a, const BigInteger &b) {
  168. if(!b.sign) {
  169. return a + (-b);
  170. }
  171. if(!a.sign) {
  172. return -((-a) + b);
  173. }
  174. if(a < b) {
  175. return -(b - a);
  176. }
  177. BigInteger ans;
  178. int carry = 0;
  179. int aa, bb;
  180. size_t lena = a.num.size();
  181. size_t lenb = b.num.size();
  182. size_t len = max(lena, lenb);
  183. ans.num.clear();
  184. for(size_t i = 0; i < len; ++i) {
  185. aa = a.num[i];
  186. if(i >= lenb) {
  187. bb = 0;
  188. } else {
  189. bb = b.num[i];
  190. }
  191. ans.num.push_back((aa - bb - carry + BigInteger::BASE) % BigInteger::BASE);
  192. if(aa < bb + carry) {
  193. carry = 1;
  194. } else {
  195. carry = 0;
  196. }
  197. }
  198. ans.setLength();
  199. return ans;
  200. }
  201. const BigInteger& BigInteger::operator-=(const BigInteger &n) {
  202. *this = *this - n;
  203. return *this;
  204. }
  205. const BigInteger& BigInteger::operator--() {
  206. *this = *this - 1;
  207. return *this;
  208. }
  209. BigInteger BigInteger::operator--(int) {
  210. BigInteger ans(*this);
  211. *this = *this - 1;
  212. return ans;
  213. }
  214. BigInteger operator*(const BigInteger &a, const BigInteger&b) {
  215. size_t lena = a.num.size();
  216. size_t lenb = b.num.size();
  217. vector<long long> ansLL;
  218. for(size_t i = 0; i < lena; ++i) {
  219. for(size_t j = 0; j < lenb; ++j) {
  220. if(i + j >= ansLL.size()) {
  221. ansLL.push_back((long long)a.num[i] * (long long)b.num[j]);
  222. } else {
  223. ansLL[i + j] += (long long)a.num[i] * (long long)b.num[j];
  224. }
  225. }
  226. }
  227. while(ansLL.back() == 0 && ansLL.size() != 1) {
  228. ansLL.pop_back();
  229. }
  230. size_t len = ansLL.size();
  231. long long carry = 0;
  232. long long tmp;
  233. BigInteger ans;
  234. ans.sign = (ansLL.size() == 1 && ansLL[0] == 0) || (a.sign == b.sign);
  235. ans.num.clear();
  236. for(size_t i = 0; i < len; ++i) {
  237. tmp = ansLL[i];
  238. ans.num.push_back((tmp + carry) % BigInteger::BASE);
  239. carry = (tmp + carry) / BigInteger::BASE;
  240. }
  241. if(carry > 0) {
  242. ans.num.push_back(carry);
  243. }
  244. ans.setLength();
  245. return ans;
  246. }
  247. const BigInteger& BigInteger::operator*=(const BigInteger &n) {
  248. *this = *this * n;
  249. return *this;
  250. }
  251. BigInteger operator/(const BigInteger &a, const BigInteger &b) {
  252. BigInteger aa(a.abs());
  253. BigInteger bb(b.abs());
  254. if(aa < bb) {
  255. return 0;
  256. }
  257. char *str = new char[aa.size() + 1];
  258. memset(str, 0, sizeof(char) * (aa.size() + 1));
  259. BigInteger tmp;
  260. int lena = aa.length;
  261. int lenb = bb.length;
  262. for(int i = 0; i <= lena - lenb; ++i) {
  263. tmp = bb.e(lena - lenb - i);
  264. while(aa >= tmp) {
  265. ++str[i];
  266. aa = aa - tmp;
  267. }
  268. str[i] += '0';
  269. }
  270. BigInteger ans(str);
  271. delete[]str;
  272. ans.sign = (ans == 0 || a.sign == b.sign);
  273. return ans;
  274. }
  275. const BigInteger& BigInteger::operator/=(const BigInteger &n) {
  276. *this = *this / n;
  277. return *this;
  278. }
  279. BigInteger operator%(const BigInteger &a, const BigInteger &b) {
  280. return a - a / b * b;
  281. }
  282. const BigInteger& BigInteger::operator%=(const BigInteger &n) {
  283. *this = *this - *this / n * n;
  284. return *this;
  285. }
  286. bool operator<(const BigInteger &a, const BigInteger &b) {
  287. if(a.sign && !b.sign) {
  288. return false;
  289. } else if(!a.sign && b.sign) {
  290. return true;
  291. } else if(a.sign && b.sign) {
  292. if(a.length < b.length) {
  293. return true;
  294. } else if(a.length > b.length) {
  295. return false;
  296. } else {
  297. size_t lena = a.num.size();
  298. for(int i = lena - 1; i >= 0; --i) {
  299. if(a.num[i] < b.num[i]) {
  300. return true;
  301. } else if(a.num[i] > b.num[i]) {
  302. return false;
  303. }
  304. }
  305. return false;
  306. }
  307. } else {
  308. return -b < -a;
  309. }
  310. }
  311. bool operator<=(const BigInteger &a, const BigInteger &b) {
  312. return !(b < a);
  313. }
  314. bool operator>(const BigInteger &a, const BigInteger &b) {
  315. return b < a;
  316. }
  317. bool operator>=(const BigInteger &a, const BigInteger &b) {
  318. return !(a < b);
  319. }
  320. bool operator==(const BigInteger &a, const BigInteger &b) {
  321. return !(a < b) && !(b < a);
  322. }
  323. bool operator!=(const BigInteger &a, const BigInteger &b) {
  324. return (a < b) || (b < a);
  325. }
  326. bool operator||(const BigInteger &a, const BigInteger &b) {
  327. return a != 0 || b != 0;
  328. }
  329. bool operator&&(const BigInteger &a, const BigInteger &b) {
  330. return a != 0 && b != 0;
  331. }
  332. bool BigInteger::operator!() {
  333. return *this == 0;
  334. }
  335. ostream& operator<<(ostream &out, const BigInteger &n) {
  336. size_t len = n.num.size();
  337. if(!n.sign) {
  338. out << '-';
  339. }
  340. out << n.num.back();
  341. for(int i = len - 2; i >= 0; --i) {
  342. out << setw(BigInteger::WIDTH) << setfill('0') << n.num[i];
  343. }
  344. return out;
  345. }
  346. istream& operator>>(istream &in, BigInteger &n) {
  347. string str;
  348. in >> str;
  349. size_t len = str.length();
  350. size_t i, start = 0;
  351. if(str[0] == '-') {
  352. start = 1;
  353. }
  354. if(str[start] == '\0') {
  355. return in;
  356. }
  357. for(i = start; i < len; ++i) {
  358. if(str[i] < '0' || str[i] > '9') {
  359. return in;
  360. }
  361. }
  362. n = str.c_str();
  363. return in;
  364. }

返回正文 ↑

重载运算符

使用代码示例

  1. #include <iostream>
  2. #include "biginteger.h"
  3. using namespace std;
  4. int main() {
  5. BigInteger a, b;
  6. cout << "========= Input Values =========" << endl;
  7. cin >> a >> b;
  8. cout << endl;
  9. cout << "========= Values =========" << endl;
  10. cout << "a = " << a << endl;
  11. cout << "b = " << b << endl;
  12. cout << endl;
  13. cout << "========= Binary Operator =========" << endl;
  14. cout << "a + b = " << a + b << endl;
  15. cout << "a - b = " << a - b << endl;
  16. cout << "a * b = " << a * b << endl;
  17. cout << "a / b = " << a / b << endl;
  18. cout << "a % b = " << a % b << endl;
  19. cout << endl;
  20. cout << "========= Relational Operator =========" << endl;
  21. cout << boolalpha;
  22. cout << "a == b is " << (a == b) << endl;
  23. cout << "a != b is " << (a != b) << endl;
  24. cout << "a < b is " << (a < b) << endl;
  25. cout << "a > b is " << (a > b) << endl;
  26. cout << "a <= b is " << (a <= b) << endl;
  27. cout << "a >= b is " << (a >= b) << endl;
  28. cout << endl;
  29. cout << "========= Logical Operator =========" << endl;
  30. cout << "a || b is " << (a || b) << endl;
  31. cout << "a && b is " << (a && b) << endl;
  32. cout << "!a is " << !a << endl;
  33. cout << endl;
  34. cout << "========= Unary Operator =========" << endl;
  35. cout << "+a = " << +a << endl;
  36. cout << "-a = " << -a << endl;
  37. cout << endl;
  38. cout << "========= Increment / Decrement Operator =========" << endl;
  39. cout << "a++ is " << a++ << endl;
  40. cout << "a = " << a << endl;
  41. cout << endl;
  42. cout << "++a is " << ++a << endl;
  43. cout << "a = " << a << endl;
  44. cout << endl;
  45. cout << "--a is " << --a << endl;
  46. cout << "a = " << a << endl;
  47. cout << endl;
  48. cout << "a-- is " << a-- << endl;
  49. cout << "a = " << a << endl;
  50. cout << endl;
  51. cout << "========= Assignment Operator =========" << endl;
  52. a += b;
  53. cout << "after a += b" << endl;
  54. cout << "a = " << a << endl;
  55. cout << "b = " << b << endl;
  56. cout << endl;
  57. a -= b;
  58. cout << "after a -= b" << endl;
  59. cout << "a = " << a << endl;
  60. cout << "b = " << b << endl;
  61. cout << endl;
  62. a *= b;
  63. cout << "after a *= b" << endl;
  64. cout << "a = " << a << endl;
  65. cout << "b = " << b << endl;
  66. cout << endl;
  67. a /= b;
  68. cout << "after a /= b" << endl;
  69. cout << "a = " << a << endl;
  70. cout << "b = " << b << endl;
  71. cout << endl;
  72. a %= b;
  73. cout << "after a %= b" << endl;
  74. cout << "a = " << a << endl;
  75. cout << "b = " << b << endl;
  76. cout << endl;
  77. return 0;
  78. }

执行测试

假设输入 a b 值分别为 123456789012345678901234567890 与 987654321098765432109876543210,则控制台展示如下:

  1. ========= Input Values =========
  2. 123456789012345678901234567890
  3. 987654321098765432109876543210
  4. ========= Values =========
  5. a = 123456789012345678901234567890
  6. b = 987654321098765432109876543210
  7. ========= Binary Operator =========
  8. a + b = 1111111110111111111011111111100
  9. a - b = -864197532086419753208641975320
  10. a * b = 121932631137021795226185032733622923332237463801111263526900
  11. a / b = 0
  12. a % b = 123456789012345678901234567890
  13. ========= Relational Operator =========
  14. a == b is false
  15. a != b is true
  16. a < b is true
  17. a > b is false
  18. a <= b is true
  19. a >= b is false
  20. ========= Logical Operator =========
  21. a || b is true
  22. a && b is true
  23. !a is false
  24. ========= Unary Operator =========
  25. +a = 123456789012345678901234567890
  26. -a = -123456789012345678901234567890
  27. ========= Increment / Decrement Operator =========
  28. a++ is 123456789012345678901234567890
  29. a = 123456789012345678901234567891
  30. ++a is 123456789012345678901234567892
  31. a = 123456789012345678901234567892
  32. --a is 123456789012345678901234567891
  33. a = 123456789012345678901234567891
  34. a-- is 123456789012345678901234567891
  35. a = 123456789012345678901234567890
  36. ========= Assignment Operator =========
  37. after a += b
  38. a = 1111111110111111111011111111100
  39. b = 987654321098765432109876543210
  40. after a -= b
  41. a = 123456789012345678901234567890
  42. b = 987654321098765432109876543210
  43. after a *= b
  44. a = 121932631137021795226185032733622923332237463801111263526900
  45. b = 987654321098765432109876543210
  46. after a /= b
  47. a = 123456789012345678901234567890
  48. b = 987654321098765432109876543210
  49. after a %= b
  50. a = 123456789012345678901234567890
  51. b = 987654321098765432109876543210
  52. Process returned 0 (0x0) execution time : 24.289 s
  53. Press any key to continue.

返回正文 ↑

其他函数

使用代码示例

  1. #include <iostream>
  2. #include "biginteger.h"
  3. using namespace std;
  4. int main() {
  5. BigInteger a = "-123456789012345678901234567890";
  6. cout << "a = " << a << endl;
  7. cout << "a.size() = " << a.size() << endl;
  8. cout << "a.e(5) = " << a.e(5) << endl;
  9. cout << "a.abs() = " << a.abs() << endl;
  10. cout << "a.abs().e(2) = " << a.abs().e(2) << endl;
  11. return 0;
  12. }

执行测试

  1. a = -123456789012345678901234567890
  2. a.size() = 30
  3. a.e(5) = -12345678901234567890123456789000000
  4. a.abs() = 123456789012345678901234567890
  5. a.abs().e(2) = 12345678901234567890123456789000
  6. Process returned 0 (0x0) execution time : 0.043 s
  7. Press any key to continue.

返回正文 ↑

性能测试

测试代码

  1. #include <fstream>
  2. #include <cmath>
  3. #include <cstdlib>
  4. #include <windows.h>
  5. #include "biginteger.h"
  6. using namespace std;
  7. typedef long long Type;
  8. const int TESTS = 80000;
  9. const char typefile[] = "type.txt";
  10. const char bigfile[] = "big.txt";
  11. const Type ZeroType = 0;
  12. const BigInteger ZeroBig = 0;
  13. Type type[TESTS + 5];
  14. BigInteger big[TESTS + 5];
  15. void Rand(bool half = false, bool Sqrt = false);
  16. void Output();
  17. void Input();
  18. void Absolute();
  19. void Compare_Calculate();
  20. int main() {
  21. ios::sync_with_stdio(false);
  22. srand((unsigned)time(NULL));
  23. Rand();
  24. Output();
  25. Input();
  26. Absolute();
  27. Compare_Calculate();
  28. return 0;
  29. }
  30. void Rand(bool half, bool Sqrt) {
  31. Type tmp;
  32. for (int i = 0; i < TESTS; ++i) {
  33. do {
  34. tmp = ((Type)rand()) << (rand() % (sizeof(Type) * 4));
  35. if(rand() % 2 == 1) {
  36. tmp *= ((Type)rand()) << (rand() % (sizeof(Type) * 4));
  37. }
  38. if(half) {
  39. tmp = abs(tmp / 2) - 1;
  40. }
  41. if(Sqrt) {
  42. if(abs(tmp) < 0) {
  43. --tmp;
  44. }
  45. tmp = sqrt(abs(tmp)) - 1;
  46. }
  47. if(rand() % 2 == 1) {
  48. tmp = -tmp;
  49. }
  50. } while(tmp == 0);
  51. type[i] = tmp;
  52. big[i] = tmp;
  53. }
  54. }
  55. void Output() {
  56. ofstream fout;
  57. int cnt;
  58. clock_t start, stop;
  59. double time_of_type, time_of_big;
  60. fout.open(typefile);
  61. cnt = 0;
  62. start = clock();
  63. while(cnt != TESTS) {
  64. fout << type[cnt++] << endl;
  65. }
  66. fout << ZeroType << endl;
  67. stop = clock();
  68. fout.close();
  69. time_of_type = stop - start;
  70. fout.open(bigfile);
  71. cnt = 0;
  72. start = clock();
  73. while(cnt != TESTS) {
  74. fout << big[cnt++] << endl;
  75. }
  76. fout << ZeroBig << endl;
  77. stop = clock();
  78. fout.close();
  79. time_of_big = stop - start;
  80. cout << "Output time of type: " << time_of_type << endl
  81. << "Output time of big: " << time_of_big << endl
  82. << "time_of_big / time_of_type = " << time_of_big / time_of_type << endl << endl;
  83. system((string("fc ") + typefile + " " + bigfile).c_str());
  84. }
  85. void Input() {
  86. ifstream fin;
  87. Type typetmp;
  88. BigInteger bigtmp;
  89. clock_t start, stop;
  90. double time_of_type, time_of_big;
  91. fin.open(typefile);
  92. start = clock();
  93. while(fin >> typetmp);
  94. stop = clock();
  95. fin.close();
  96. time_of_type = stop - start;
  97. fin.open(bigfile);
  98. start = clock();
  99. while(fin >> bigtmp);
  100. stop = clock();
  101. fin.close();
  102. time_of_big = stop - start;
  103. cout << "Input time of type: " << time_of_type << endl
  104. << "Input time of big: " << time_of_big << endl
  105. << "time_of_big / time_of_type = " << time_of_big / time_of_type << endl << endl;
  106. }
  107. void Absolute() {
  108. int cnt;
  109. ofstream fout;
  110. clock_t start, stop;
  111. double time_of_type, time_of_big;
  112. fout.open(typefile);
  113. cnt = 0;
  114. start = clock();
  115. while(cnt != TESTS) {
  116. if(type[cnt] == BigInteger::LONG_LONG_MIN) {
  117. fout << "9223372036854775808" << endl;
  118. } else if(type[cnt] == INT_MIN) {
  119. fout << "2147483648" << endl;
  120. } else {
  121. fout << abs(type[cnt]) << endl;
  122. }
  123. ++cnt;
  124. }
  125. fout << abs(ZeroType) << endl;
  126. stop = clock();
  127. fout.close();
  128. time_of_type = stop - start;
  129. fout.open(bigfile);
  130. cnt = 0;
  131. start = clock();
  132. while(cnt != TESTS) {
  133. fout << big[cnt].abs() << endl;
  134. ++cnt;
  135. }
  136. fout << ZeroBig.abs() << endl;
  137. stop = clock();
  138. fout.close();
  139. time_of_big = stop - start;
  140. cout << "Abs time of type: " << time_of_type << endl
  141. << "Abs time of big: " << time_of_big << endl
  142. << "time_of_big / time_of_type = " << time_of_big / time_of_type << endl << endl;
  143. system((string("fc ") + typefile + " " + bigfile).c_str());
  144. }
  145. template<typename T>
  146. void cmpcal(T *arr, int command, ofstream &fout) {
  147. int cnt;
  148. const T ZERO = 0;
  149. cnt = 0;
  150. while(cnt != TESTS) {
  151. switch(command) {
  152. case 1: {
  153. fout << (arr[cnt] == arr[cnt + 1]) << endl
  154. << (arr[cnt] != arr[cnt + 1]) << endl
  155. << (arr[cnt] < arr[cnt + 1]) << endl
  156. << (arr[cnt] <= arr[cnt + 1]) << endl
  157. << (arr[cnt] > arr[cnt + 1]) << endl
  158. << (arr[cnt] >= arr[cnt + 1]) << endl;
  159. break;
  160. }
  161. case 2: fout << arr[cnt] / arr[cnt + 1] << endl; break;
  162. case 3: fout << arr[cnt] % arr[cnt + 1] << endl; break;
  163. case 4: fout << arr[cnt] + arr[cnt + 1] << endl; break;
  164. case 5: fout << arr[cnt] - arr[cnt + 1] << endl; break;
  165. case 6: fout << arr[cnt] * arr[cnt + 1] << endl; break;
  166. default: break;
  167. }
  168. cnt += 2;
  169. }
  170. switch(command) {
  171. case 2: fout << ZERO / arr[0] << endl; break;
  172. case 3: fout << ZERO % arr[0] << endl; break;
  173. case 4: fout << ZERO + arr[0] << endl << arr[0] + ZERO << endl; break;
  174. case 5: fout << ZERO - arr[0] << endl << arr[0] - ZERO << endl; break;
  175. case 6: fout << ZERO * arr[0] << endl << arr[0] * ZERO << endl; break;
  176. default: break;
  177. }
  178. }
  179. void Compare_Calculate() {
  180. ofstream fout;
  181. clock_t start, stop;
  182. double time_of_type, time_of_big;
  183. string command[6] = {"Compare", "Div", "Mod", "Add", "Cut", "Multiply"};
  184. for(int i = 1; i <= 6; ++i) {
  185. switch(i) {
  186. case 4: Rand(true, false); break;
  187. case 6: Rand(false, true); break;
  188. default: break;
  189. }
  190. fout.open(typefile);
  191. start = clock();
  192. cmpcal(type, i, fout);
  193. stop = clock();
  194. fout.close();
  195. time_of_type = stop - start;
  196. fout.open(bigfile);
  197. start = clock();
  198. cmpcal(big, i, fout);
  199. stop = clock();
  200. fout.close();
  201. time_of_big = stop - start;
  202. cout << command[i - 1] << " time of type: " << time_of_type << endl
  203. << command[i - 1] << " time of big: " << time_of_big << endl
  204. << "time_of_big / time_of_type = " << time_of_big / time_of_type << endl << endl;
  205. system((string("fc ") + typefile + " " + bigfile).c_str());
  206. }
  207. }

测试结果

由于数据随机生成,每次结果输出不保证完全一致。

  1. Output time of type: 414
  2. Output time of big: 440
  3. time_of_big / time_of_type = 1.0628
  4. 正在比较文件 type.txt BIG.TXT
  5. FC: 找不到差异
  6. Input time of type: 58
  7. Input time of big: 95
  8. time_of_big / time_of_type = 1.63793
  9. Abs time of type: 417
  10. Abs time of big: 523
  11. time_of_big / time_of_type = 1.2542
  12. 正在比较文件 type.txt BIG.TXT
  13. FC: 找不到差异
  14. Compare time of type: 1261
  15. Compare time of big: 1722
  16. time_of_big / time_of_type = 1.36558
  17. 正在比较文件 type.txt BIG.TXT
  18. FC: 找不到差异
  19. Div time of type: 210
  20. Div time of big: 1352
  21. time_of_big / time_of_type = 6.4381
  22. 正在比较文件 type.txt BIG.TXT
  23. FC: 找不到差异
  24. Mod time of type: 205
  25. Mod time of big: 1785
  26. time_of_big / time_of_type = 8.70732
  27. 正在比较文件 type.txt BIG.TXT
  28. FC: 找不到差异
  29. Add time of type: 203
  30. Add time of big: 546
  31. time_of_big / time_of_type = 2.68966
  32. 正在比较文件 type.txt BIG.TXT
  33. FC: 找不到差异
  34. Cut time of type: 217
  35. Cut time of big: 540
  36. time_of_big / time_of_type = 2.48848
  37. 正在比较文件 type.txt BIG.TXT
  38. FC: 找不到差异
  39. Multiply time of type: 204
  40. Multiply time of big: 358
  41. time_of_big / time_of_type = 1.7549
  42. 正在比较文件 type.txt BIG.TXT
  43. FC: 找不到差异
  44. Process returned 0 (0x0) execution time : 11.558 s
  45. Press any key to continue.

返回正文 ↑

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注