1. 概述
GMP是一個開源的數學運算庫,它可以用於任意精度的數學運算,包括有符號整數、有理數和浮點數,是進行大數運算比較好的選擇。
需要說明的是,在Windows環境下編譯GMP庫不是很容易的一件事情,如果可以的話,還是找一下已經編譯好的庫文件直接調用。GMP是C語言編寫的庫,在接口方面是比較穩定的,理論上是甚至能夠做到跨語言調用。
2. 編譯
2.1. GCC環境
GMP庫只提供了一個Makefile文件,這意味着需要GCC環境的支持。在Windows下使用GCC就需要MinGW了,但是MinGW是支持32位編譯的,如果要編譯64位的話,就得使用MinGW-w64了。MinGW-w64是MinGW的升級版本(MinGW已經不更新了),能夠編譯64位和32位。但是,沒錯還有但是隻有MinGW-w64是沒辦法編譯Makefile文件的,單獨的MinGW-w64環境只能自己一個個編譯鏈接源代碼。編譯Makefile文件需要安裝msys2,msys2可以在Windows下搭建一個類linux環境,裏面不僅集成了MinGW-w64,還可以包括bash、vim、gcc、make等工具包。
所以知道這裏面有多繞了吧?要編譯GMP只需要下載msys2就行了,當初我可是把MinGW、MinGW-w64都下載嘗試了一遍。當然使用msys2也是有坑的,msys2的工具包需要在線下載,地址在國外的工具包下載很慢,這個時候就需要更換國內數據源纔行。其中的具體的安裝過程可以參考文章結尾出的文獻[1],記得一定要安裝gcc和make。
2.2. 編譯過程
在msys2中配置好gcc和make工具包之後,啓動工作目錄下的msys2環境。在msys2安裝目錄下有msys2.exe和mingw64.exe兩個啓動入口,可以都試試,看是否支持make指令,理論上兩者都是可以使用的:
啓動msys2環境後,通過CD命令進入到GMP的源代碼目錄,依次輸入如下指令:
./configure
make
make install
就可以編譯出靜態包,如果需要動態庫,那麼可以把第一條指令修改爲:
./configure --disable-static --enable-shared
這裏建議使用動態庫。
3. 使用
3.1. 調用
另外一個頭痛的問題就是mingw編譯出來的靜態庫後綴名爲.a,編譯出來的動態庫的導入庫後綴名爲.dll.a,而在Windows下一般使用.lib的來作爲靜態庫或者動態庫的導入庫。好在VS中是能夠識別.a文件作爲導入庫的,像加載.lib一樣加載dll.a即可:
#pragma comment(lib, "libgmp.dll.a")
注意使用動態庫時,單獨運行時可能會提示缺少dll,libgmp.dll還依賴了mingw中的一些運行時庫,根據提示找到相應的dll即可。
3.2. 示例
在VS環境中設置好動態庫環境,使用實例代碼如下:
#include <iostream>
#include "gmp.h"
using namespace std;
int main()
{
//計算2的1000次方
{
size_t a = 1;
for (int i = 0; i < 1000; i++)
{
a *= 2;
}
cout << "2^1000 = " << a << endl;
}
{
mpz_t a, b, c, d;
mpz_init(a);
mpz_init(b);
mpz_init(c);
mpz_init(d);
//計算2的1000次方
mpz_init_set_ui(a, 2);
mpz_pow_ui(c, a, 1000);
gmp_printf("c = %Zd\n", c);
}
//大數運算
{
mpz_t b, c, d;
mpz_init(b);
mpz_init(c);
mpz_init(d);
//計算12345678900987654321*98765432100123456789
mpz_init_set_str(b, "12345678900987654321", 10);//10進制
mpz_init_set_str(c, "98765432100123456789", 10);
mpz_mul(d, b, c);
gmp_printf("d = %Zd\n", d);
mpz_clear(b);
mpz_clear(c);
mpz_clear(d);
}
return 0;
}
以上演示了使用大數冪運算和乘法運算的過程,運行結果如下:
最後附上我編譯的GMP地址。