簡體   English   中英

無法以理智的方式在 windows 下使用 gmp 和 uint64_t

[英]Unable to work with gmp and uint64_t under windows in a sane manner

以下代碼在 Linux/Debian (g++ 10.2) 下運行良好(編譯,斷言語句為真),但拒絕在 Windows (mingw64 g++ 12.2.0) 下運行。 它基本上只是應該將UINT64_MAX分配給gmp庫中的mpf_class ,但似乎 gmp 的mpf_class沒有為uint64_t定義構造函數和運算符,它在我試圖在這里使用的 windows 環境中是 unsigned long long int。 我敢打賭現在沒有看到一個簡單的解決方法,因為現在是星期五而且很晚,對嗎?

#include <gmpxx.h> // link with gmp + gmpxx
#include <string>

/// Helper to convert mpf_class to std::string
[[nodiscard]] inline std::string mpf_class_to_str(const mpf_class& num) {
    mp_exp_t exponent(1);
    return num.get_str(exponent, 10);
}

int main() {
    mpf_class y = UINT64_MAX; // defined in my mingw64 as 0xffffffffffffffffULL
    //            ^
    //            |  adding no cast -> compile error
    //               adding (unsigned int) cast -> compiles, but assertion below false
    //               adding (uint64_t) cast -> compile error

    y *= UINT64_MAX; // UINT64_MAX²
    assert(mpf_class_to_str(y) == "340282366920938463426481119284349108225");
}

編譯錯誤 g++ 給我的是:

error: conversion from 'long long unsigned int' to 'mpf_class' is ambiguous
   31 |             mpf_class y = UINT64_MAX;
      |                           ^~~~~~~~~~

然后它列出了所有候選人,基本上是(取自gmpxx.h而不是錯誤日志):

#define __GMPXX_DEFINE_ARITHMETIC_CONSTRUCTORS      \
  __gmp_expr(signed char c) { init_si(c); }     \
  __gmp_expr(unsigned char c) { init_ui(c); }       \
  __gmp_expr(signed int i) { init_si(i); }      \
  __gmp_expr(unsigned int i) { init_ui(i); }        \
  __gmp_expr(signed short int s) { init_si(s); }    \
  __gmp_expr(unsigned short int s) { init_ui(s); }  \
  __gmp_expr(signed long int l) { init_si(l); }     \
  __gmp_expr(unsigned long int l) { init_ui(l); }   \
  __gmp_expr(float f) { init_d(f); }            \
  __gmp_expr(double d) { init_d(d); }

如果我操縱 header 添加行__gmp_expr(unsigned long long int l) { init_ui(l); } __gmp_expr(unsigned long long int l) { init_ui(l); }都很好,只是這對我來說太臟了。

mpz_class不能從(unsigned) long long構造。 文檔中也有說明。

該庫不支持(unsigned) long long 請參閱此處的郵件列表線程(以及幾個較舊的線程)。 在回答中,Marc Glisse 還指出這主要是 Windows 上的一個問題。

他還在此處建議了一個補丁來支持問題的 C++ 初始化/轉換部分,但我在 gmp 的公共開發存儲庫中找不到它。 正如他在消息中指出的那樣,這不會涵蓋算術運算等。

除了按照user17732522 的回答中的建議修補 gmp 庫之外,還可以通過使用轉換助手 function 讓我的示例工作。像這樣:

/// Helper for converting anything to mpf_class.
namespace bigdec {
template<typename T> [[nodiscard]] inline
mpf_class get(const T& num) {
    std::stringstream ss;
    ss << num;
    mpf_class bigdec;
    bigdec.set_str(ss.str(), 10);
    return bigdec;
}}

並相應地改變用法:

int main() {
    mpf_class y = bigdec::get(UINT64_MAX); // <- here
    y *= bigdec::get(UINT64_MAX);          // <- and here
    assert(mpf_class_to_str(y) == "340282366920938463426481119284349108225");
}

現在它編譯並且斷言在我的 Linux 和 Windows 環境中都為真。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM