gmp将uint*的数据转换成mpz格式

在 GMP (GNU Multiple Precision Arithmetic Library) 中将 uint*_t 类型的数据(如 uint32_t, uint64_t)转换为 mpz_t 类型,有几种常见方法。

方法 1:使用 mpz_set_ui(适合 32/64 位无符号整数)

适用于 uint32_tuint64_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_tuint64_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

总结

方法

适用场景

优点

缺点

mpz_set_ui

32/64 位整数(直接赋值)

简单高效

不适用于 >64 位

mpz_import

任意长度二进制数据(如 uint8_t 数组)

支持字节序,灵活

需注意字节序问题

手动移位构造

需要逐位控制的情况

兼容性强

性能较低

推荐选择

  • 如果是 uint32_t/uint64_t,直接用 mpz_set_ui
  • 如果是 字节数组自定义大整数,用 mpz_import
  • 如果需要 位级操作,用手动构造。
#include <iostream> #include <cmath> #include <chrono> #include <thread> #include <vector> #include <gmpxx.h> #include <fstream> #include <sstream> #include <iomanip> #include <mutex> #include <atomic> #include <sys/sysinfo.h> #include <sys/resource.h> #include <fstream> #include <unistd.h> #include <nvml.h> // NVIDIA GPU监控 std::mutex output_mutex; std::atomic<bool> stop_monitor(false); mpf_class pi_value(0, 0); // 高精度π值 std::atomic<int> iteration_count(0); // 获取CPU使用率 double get_cpu_usage() { static uint64_t last_total = 0, last_idle = 0; std::ifstream stat_file("/proc/stat"); std::string line; std::getline(stat_file, line); std::istringstream iss(line); std::string cpu; uint64_t user, nice, system, idle, iowait, irq, softirq, steal; iss >> cpu >> user >> nice >> system >> idle >> iowait >> irq >> softirq >> steal; uint64_t total = user + nice + system + irq + softirq + steal; uint64_t idle_time = idle + iowait; double usage = 0.0; if (last_total != 0) { uint64_t total_diff = total - last_total; uint64_t idle_diff = idle_time - last_idle; usage = 100.0 * (1.0 - static_cast<double>(idle_diff) / total_diff); } last_total = total; last_idle = idle_time; return usage; } // 获取内存使用率 double get_memory_usage() { struct sysinfo mem_info; sysinfo(&mem_info); double total = mem_info.totalram; double free = mem_info.freeram; return 100.0 * (1.0 - free / total); } // 获取GPU使用率 (NVIDIA) double get_gpu_usage() { nvmlReturn_t result; nvmlDevice_t device; unsigned int utilization; result = nvmlInit(); if (result != NVML_SUCCESS) return -1.0; result = nvmlDeviceGetHandleByIndex(0, &device); if (result != NVML_SUCCESS) { nvmlShutdown(); return -1.0; } result = nvmlDeviceGetUtilizationRates(device, &utilization); if (result != NVML_SUCCESS) { nvmlShutdown(); return -1.0; } nvmlShutdown(); return static_cast<double>(utilization.gpu); } // 资源监控线程函数 void monitor_resources() { while (!stop_monitor) { double cpu = get_cpu_usage(); double mem = get_memory_usage(); double gpu = get_gpu_usage(); { std::lock_guard<std::mutex> lock(output_mutex); std::cout << "\033[2K"; // 清除当前行 std::cout << "\r[资源监控] CPU: " << std::fixed << std::setprecision(1) << cpu << "% | " << "内存: " << mem << "% | " << "GPU: " << (gpu >= 0 ? std::to_string(static_cast<int>(gpu)) + "%" : "N/A"); std::cout.flush(); } std::this_thread::sleep_for(std::chrono::seconds(1)); } } // Chudnovsky算法计算π mpf_class chudnovsky_pi(unsigned int precision, unsigned int iterations) { mpf_set_default_prec(precision); mpf_class pi(0, precision); mpf_class sum(0, precision); mpf_class k1(13591409, precision); mpf_class k2(545140134, precision); mpf_class k3(-262537412640768000, precision); mpf_class k4(426880, precision); mpf_class k5(10005, precision); mpf_class sqrt_c(0, precision); k5 = sqrt(k5); sqrt_c = k4 * k5; mpz_class a(1); mpz_class b(1); mpz_class a_prime(1); mpz_class b_prime(1); for (unsigned int k = 0; k < iterations; k++) { mpf_class numerator(0, precision); mpf_class denominator(0, precision); if (k == 0) { a = 1; b = 1; } else { // 使用二进制分裂法优化计算 a_prime = (6*k-5)*(2*k-1)*(6*k-1); b_prime = k*k*k * k3 / 24; a *= a_prime; b *= b_prime; } numerator = k1 + k2 * k; denominator = a * b; sum += numerator / denominator; iteration_count = k + 1; // 每100次迭代显示进度 if (k % 100 == 0) { pi = sqrt_c / sum; std::lock_guard<std::mutex> lock(output_mutex); std::cout << "\n[计算进度] 迭代: " << k << "/" << iterations << " | 当前π值: " << std::setprecision(15) << pi << std::endl; } } pi = sqrt_c / sum; return pi; } int main() { const unsigned int precision = 100000; // 二进制精度位 const unsigned int iterations = 1000; // 迭代次数 std::cout << "开始计算π值 (Chudnovsky算法)..." << std::endl; std::cout << "精度: " << precision << "位 | 最大迭代: " << iterations << std::endl; // 启动资源监控线程 std::thread monitor_thread(monitor_resources); // 记录开始时间 auto start_time = std::chrono::high_resolution_clock::now(); // 计算π值 pi_value = chudnovsky_pi(precision, iterations); // 记录结束时间 auto end_time = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time); // 停止监控线程 stop_monitor = true; monitor_thread.join(); // 输出最终结果 std::cout << "\n\n计算完!" << std::endl; std::cout << "耗时: " << duration.count() / 1000.0 << " 秒" << std::endl; std::cout << "最终π值(前50位): " << std::setprecision(50) << pi_value << std::endl; return 0; } 修复代码错误 default.cpp:6:10: fatal error: 'gmpxx.h' file not found #include <gmpxx.h> ^~~~~~~~~ 1 error generated.
07-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值