在 GMP (GNU Multiple Precision Arithmetic Library) 中将 uint*_t 类型的数据(如 uint32_t, uint64_t)转换为 mpz_t 类型,有几种常见方法。
方法 1:使用 mpz_set_ui(适合 32/64 位无符号整数)
适用于 uint32_t 或 uint64_t 数据,直接赋值:
#include<stdint.h>
#include<stdio.h>
#include<gmp.h>
void uint32_to_mpz(mpz_t result, uint32_t value)
{
// set directly
mpz_set_ui(result, value);
}
void uint64_to_mpz(mpz_t result, uint64_t value)
{
// 如果系统支持 64 位,可以直接用 mpz_set_ui(部分 GMP 版本支持)
#if __GMP_BITS_PER_MP_LIMB >= 64
mpz_set_ui(result, value);
#else
// 分高低32位处理
mpz_set_ui(result, (uint32_t)(value >> 32)); // high 32bits
mpz_mul_2exp(result, result, 32); // left move 32 bits
mpz_add_ui(result, result, (uint32_t)value); // low 32 bits
#endif
}
int main()
{
mpz_t num1, num2, num3;
mpz_inits(num1, num2, num3, NULL);
uint32_t u32 = 0x12345678;
uint64_t u64 = 0x123456789abcdef0;
// method 1, use mpz_set_ui;
uint32_to_mpz(num1, u32);
uint64_to_mpz(num2, u64);
gmp_printf("uint32_t → mpz_t: %Zu\n", num1);
gmp_printf("uint64_t → mpz_t: %Zu\n", num2);
}
适用场景:
- 适用于
uint32_t或uint64_t的直接转换。 - 在 32 位系统上,
uint64_t需要分段处理。
方法 2:使用 mpz_import(适合任意长度二进制数据)
适用于 uint8_t 数组或更大的 uint*_t 数据(如 uint128_t 或自定义大整数):
#include <gmp.h>
#include <stdint.h>
void uint64_to_mpz_import(mpz_t result, uint64_t val) {
// 使用 mpz_import 导入二进制数据
mpz_import(
result, // 目标 mpz_t
1, // 导入 1 个 "word"(64 位)
-1, // 小端序 (-1 = LSB first)
sizeof(val), // 每个 word 的字节数(8)
0, // 本地字节序
0, // nails(未使用的位,设为 0)
&val // 数据指针
);
// mpz_import(result, 1, -1, sizeof(val), 0, 0, &val);
}
// 示例:转换 uint8_t 数组(如 16 字节的 uint128_t)
void uint8_array_to_mpz(mpz_t result, const uint8_t *data, size_t len) {
mpz_import(
result,
len, // word 数量(每个 word 1 字节)
-1, // 小端序 (-1 = LSB first)
1, // 每个 word 1 字节
0, // 本地字节序
0,
data
);
// mpz_import(result, len, -1, 1, 0, 0, data);
}
适用场景:
- 适用于
uint8_t/uint16_t/uint32_t/uint64_t数组。 - 支持 任意长度 的二进制数据(如 128 位、256 位整数)。
- 可指定 字节序(大端序或小端序)。
方法 3:手动移位构造(兼容性强)
适用于需要逐位构造 mpz_t 的情况(如从字节流构建):
#include <gmp.h>
#include <stdint.h>
void uint64_to_mpz_manual(mpz_t result, uint64_t val) {
mpz_set_ui(result, 0);
for (int i = 0; i < 64; i++) {
if (val & (1ULL << i)) {
mpz_setbit(result, i); // 设置对应位
}
}
}
适用场景:
- 适用于需要 逐位处理 的情况(如位掩码操作)。
- 性能较低,但灵活性高。
完整示例代码
#include<stdint.h>
#include<stdio.h>
#include<gmp.h>
void uint32_to_mpz(mpz_t result, uint32_t value)
{
// set directly
mpz_set_ui(result, value);
}
void uint64_to_mpz(mpz_t result, uint64_t value)
{
// 如果系统支持 64 位,可以直接用 mpz_set_ui(部分 GMP 版本支持)
#if __GMP_BITS_PER_MP_LIMB >= 64
mpz_set_ui(result, value);
#else
// 分高低32位处理
mpz_set_ui(result, (uint32_t)(value >> 32)); // high 32bits
mpz_mul_2exp(result, result, 32); // left move 32 bits
mpz_add_ui(result, result, (uint32_t)value); // low 32 bits
#endif
}
void uint64_to_mpz_import(mpz_t result, uint64_t val)
{
mpz_import(result, 1, -1, sizeof(val), 0, 0, &val);
}
void uint8_array_to_mpz(mpz_t result, const uint8_t *data, size_t len)
{
mpz_import(result, len, -1, 1, 0, 0, data);
}
//逐位构造 mpz_t
void uint64_to_mpz_manual(mpz_t result, uint64_t val)
{
mpz_set_ui(result, 0);
for (int i = 0; i < 64; i++)
{
if (val & (1ULL << i))
{
mpz_setbit(result, i);
}
}
}
int main()
{
mpz_t num1, num2, num3;
mpz_inits(num1, num2, num3, NULL);
uint32_t u32 = 0x12345678;
uint64_t u64 = 0x123456789abcdef0;
// method 1, use mpz_set_ui;
uint32_to_mpz(num1, u32);
uint64_to_mpz(num2, u64);
gmp_printf("uint32_t → mpz_t: %Zu\n", num1);
gmp_printf("uint64_t → mpz_t: %Zu\n", num2);
// method 2, use import
uint64_to_mpz_import(num1, u64);
uint8_array_to_mpz(num2, (uint8_t *)&u64, 8);
gmp_printf("uint64_to_mpz_import → mpz_t: %Zu\n", num1);
gmp_printf("uint8_array_to_mpz → mpz_t: %Zu\n", num2);
// method 3, bit by bit set mpz
uint64_to_mpz_manual(num3, u64);
gmp_printf("uint64_to_mpz_manual ->mpz :%Zu\n", num3);
return 0;
}
输出:
uint32_t → mpz_t: 305419896
uint64_t → mpz_t: 1311768467463790320
uint64_to_mpz_import → mpz_t: 1311768467463790320
uint8_array_to_mpz → mpz_t: 1311768467463790320
uint64_to_mpz_manual ->mpz :1311768467463790320
总结
|
方法 |
适用场景 |
优点 |
缺点 |
|
|
32/64 位整数(直接赋值) |
简单高效 |
不适用于 >64 位 |
|
|
任意长度二进制数据(如 uint8_t 数组) |
支持字节序,灵活 |
需注意字节序问题 |
|
手动移位构造 |
需要逐位控制的情况 |
兼容性强 |
性能较低 |
推荐选择:
- 如果是
uint32_t/uint64_t,直接用mpz_set_ui。 - 如果是 字节数组 或 自定义大整数,用
mpz_import。 - 如果需要 位级操作,用手动构造。
448

被折叠的 条评论
为什么被折叠?



