如何将字节从 uint64_t 转换为 double?

Posted

技术标签:

【中文标题】如何将字节从 uint64_t 转换为 double?【英文标题】:How to convert bytes from uint64_t to double? 【发布时间】:2020-12-29 10:42:14 【问题描述】:

我有二进制文件,我从中读取 uint64_t val(使用 little-endian)。现在我想将这个uint64_t 转换为double(不仅仅是强制转换,而是如果我从文件中输入的数字,则正好是double)。所以应该有相同的位表示。我该怎么做?

【问题讨论】:

memcpyuint64_t 变成double 您是将 64 位整数转换为双精度还是将 8 字节转换为 double 创建一个double 变量。将 uint64_t 分配给 double 变量。 @ThomasMatthews,它们将具有相同的值但不同的位表示。 @ThomasMatthews 来自问题:“所以应该具有相同的位表示。” 【参考方案1】:

简单的便携方式:

uint64_t u64 = read_from_file();
double d;
memcpy(&d, &u64, sizeof(d));

大多数编译器只会为此生成几条指令。

【讨论】:

@RichardMcFriendOluwamuyiwa:什么不起作用?代码是否无法将uint64_t 的位重新解释为double,或者编译器是否会生成对memcpy() 的调用?什么CPU?什么编译器?有什么选择?【参考方案2】:

这是一种方法:

uint64_t val = someCodeThatReadsTheValue();
auto valPtr = &val;
double dVal = *reinterpret_cast<double*>(valPtr);

正如 cmets 中所指出的,这是未定义行为,尽管它适用于大多数编译器。

如果您不想信任您的编译器,您可以执行以下操作。

uint64_t val1 = someCodeThatReadsTheValue();
double val2;
char* p1 = reinterpret_cast<char*>(&val1);
char* p2 = reinterpret_cast<char*>(&val2);
for(int i = 0; i < sizeof(uint64_t); i++)
    p2[i] = p1[i];

删除这个只是一个有趣的事实,使用memcpy 更容易,就像@chqrlie 的答案一样。除非你不能使用 C 标准库。

【讨论】:

是未定义的行为 当您通过不兼容的类型访问数据时,此解决方案会调用未定义的行为。 帮助阅读:en.cppreference.com/w/cpp/language/… 还有这个:gist.github.com/shafik/848ae25ee209f698763cffee272a58f8 @DavidC.Rankin 联合解决方案对 C 有效,但通过联合进行类型双关对 C++ 来说是未定义的行为。

以上是关于如何将字节从 uint64_t 转换为 double?的主要内容,如果未能解决你的问题,请参考以下文章

如何将字节数组转换为 boost::multiprecision::uint128_t?

是否有一种定义明确且高性能的方式将双精度位转换为 uint64_t 并返回

从uint32_t [16]数组到uint32_t变量序列的64位副本

如何将 32 字符(0/1)的序列转换为 32 位(uint32_t)?

为啥在 gcc 和 clang 上通过优化将大 double 转换为 uint16_t 会给出不同的答案

防止将 uint64_t 转换为 uint16_t