1. 创作前
1.1 关于C++
C++本身有内建的整数类型,但这些类型能表示的数的范围非常有限,比如 unsigned long long
只能表示0~18446744073709551615的数;
1.2 关于网络上的高精度整数类
CSDN上有很多创作者开发的高精度整数类,但是大多数都是用一个char型数组存储每一位数字(甚至有的用整型数组存储每一位数字),但这种存储方式浪费空间,因为一个char型的变量有256种状态,而你用了能表示256种状态的char只表示了10种状态(
1.3 著名的库
1.3.1 Java BigInteger
BigInteger是JDK里自带的高精度整数类,相信写过Java的小伙伴们都不陌生吧~
1.3.2 libgmp
GMP(The GNU Multiple Precision Arithmetic Library)又叫GNU多精度算术库,是一个提供了很多操作高精度的大整数,浮点数的运算的算术库,主要应用领域是密码学的应用和研究、互联网安全应用、代数系统、计算代数研究等。
GMP是个非常强大的库,提供了很多高效的算法,并且进行了目标机器优化!
所以一般来说我们写的程序运行速度是远远不如GMP的。。。
1.4 创作目的
- 提供一个小巧到可以随意嵌入你的课设的较完整的高精度整数实现
- 锻炼写项目能力和debug能力
- 了解并运用与高精度整数相关的算法
2. 开发环境和项目搭建
2.1 开发环境
操作系统:Windows 11
IDE:CLion 2023.1
代码编写辅助工具:Code Whisperer
2.2 项目搭建
- 打开CLion,选择文件-新建-项目,如图所示
C++标准选择C++23,因为可能会用到C++新标准的东西 - 在项目面板上任意位置右键,新建 - C++类,类的名称填iBigInteger,别的保持默认值
3. 正式编写代码
3.1 数的存储方式
在Java BigInteger中,数以二进制的形式存储在int型数组中,每个int存储大整数的32个二进制位,这样可以保证内存空间被充分利用;
在我们的iBigInteger中,沿用这种做法,但是我们用了更方便功能更全的std::vector代替数组(不用担心std::vector的运行时开销比数组大,因为C++有个零开销抽象原则;
另外,用一个bool型变量存储数的符号,即这个数是正数还是负数;
因为有了单独的“符号位”,所以存储在vector中的数都是正的,所以vector的类型参数为unsigned int;
综上所述,class iBigInteger
中所有的数据成员有:
- std::vector ,命名为v;
- bool,命名为_flag;
#ifndef IBIGINTEGER_DEMO_IBIGINTEGER_H
#define IBIGINTEGER_DEMO_IBIGINTEGER_H
#include <vector>
class iBigInteger {
std::vector<unsigned> v;
bool _flag;
};
#endif //IBIGINTEGER_DEMO_IBIGINTEGER_H
3.2 构造函数
3.2.1 iBigInteger()
符号为true
,v
中构造一个元素0;
iBigInteger::iBigInteger() {
v.emplace_back(0);
_flag = true;
}
3.2.2 iBigInteger(int)
和iBigInteger(unsigned int)
unsigned int
:因为vector中的元素恰好是unsigned int
,所以_flag
为true
,v
中构造一个元素,它的值等于参数;iBigInteger::iBigInteger(unsigned i) { v.emplace_back(i); _flag = true; }
int
:如果参数大于0,则v
中构造一个元素,它的值等于参数,同时_flag
为true
;如果参数小于0,则v
中构造一个元素,它的值等于参数的相反数,同时_flag
=false
;iBigInteger::iBigInteger(int i) { v.emplace_back(i > 0 ? i : -i); if (i > 0) _flag = true; else _flag = false; }
3.2.3 iBigInteger(long long)
和iBigInteger(unsigned long long)
unsigned long long
(设形参名为i):_flag
为true;- 如果参数=0,则
v
中构造0; - 如果参数不等于0:
v
中构造一个数,值等于i&4294967295(即i的最后32位)- 如果i>>32(i的前32位)不等于0,则
v
中构造第二个数,值等于i>>32
iBigInteger::iBigInteger(unsigned long long i) { if (i == 0) { v.emplace_back(0); } else { v.emplace_back(i & (unsigned) 0xffffffff); if ((i >> 32) > 0)v.emplace_back(i >> 32); } _flag = true; }
long long
:(设形参名为i):- 如果参数=0,
_flag
为true
,v
中构造0; - 如果参数>0,
_flag
为true
;v
中构造一个数,值等于i&4294967295(即i的最后32位)- 如果i>>
- 如果参数=0,