大整数类 BigInt

Posted izlyforever

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了大整数类 BigInt相关的知识,希望对你有一定的参考价值。

把自己的 个人C++17代码模板库 放在 github 后,发现没有 BigInt,于是有了这篇博客,搜了一下相当有的几个例子,发现都不够全面,或者说不够高效,于是就自己尝试一下。那么就有几个问题

  • 用什么存数据
  • 内部逻辑几进制
  • 乘法和除法怎么实现
  • 最终哪些功能要实现
  • 与 Boost 的大数比较性能如何

代码仓库,这里就当作放文档的地方吧

存储

首先肯定会用类似多项式方式存大数,自然会想到用 vector<T>,现在问题是 \\(T\\) 是什么

  • 不能是 bool,因为 vector<bool> 不是容器,水很深,我把握不住。
  • char, short, int, long long 选什么呢?因为我要用 NTT,因此只能在 int 和 long long 中选择,但是如果用 long long 基础乘法时不可避免出现 __int128 十分影响效率,最终选择 int
  • 有符号还是无符号:有符号,因为在出现 NTT 会出现减法,此时很可能就会模 \\(2^{32}\\) 直接爆炸

再用一个 flag 存储符号。

逻辑

先继承 vector<int> 然后用 sgn 存储符号。

  • 取负号,自己改变符号(为了高效),+ 也太鸡肋了就不搞了,判断是否相等
  • 实现大小比较
  • 实现加法减法
  • 实现逻辑比较
  • 用 NTT 实现乘法
  • 用 牛顿法实现除法

由于 NTT 的使用中,能选取的最佳模数为 \\(469762049 = 7 \\cdot 2^{26} + 1\\) 又由于 \\(2^{2^{25}} \\simeq 10^{10^7}\\) ,所以数的十进制表示长度不能超过 \\(10^7\\)(其实如果超过了一次除法,甚至乘法估计也是跑不动的)

基础功能

  • +=,-=,*=,/=
  • ++,--(前缀),后缀版本太蠢了
  • 位运算
  • 与基础数据交互,类型转化int, LL, string
  • IO
  • 支持 lg(2 为底数)

拓展功能

  • gcd,lcm, pow,sqrt,cbrt,任意次开方
  • 静态:big_random: 利用 mt19937?

与 Boost 比较

#include <boost/multiprecision/cpp_int.hpp>
using BINT = boost::multiprecision::cpp_int;

以上是关于大整数类 BigInt的主要内容,如果未能解决你的问题,请参考以下文章

定义一个大整数类,并重载乘法*运算符

将整数类型的所有主键更改为 bigint,包括引用

超出JavaScript安全整数限制的数字计算-BigInt

Java BigInteger类知识点总结

用整数替换 sqlite.net “bigint” 以实现自动增量主键约束

前端面试 JavaScript— 什么是BigInt? 谈谈你对它的认识