【问题标题】:C/C++ Initialise double with hexC/C++ 用十六进制初始化双精度
【发布时间】:2026-01-25 19:25:01
【问题描述】:

我想用一个十六进制常量初始化一个双精度数。

double dbl = 0xFEDCBA9876543212;
printf("dbl: %llX\n", (uint64_t)dbl);

我希望看到输出:

dbl: FEDCBA9876543212

但我得到了:

dbl: FEDCBA9876543000

为什么会这样,为什么最后 3 个字节被丢弃?

【问题讨论】:

  • 这样做可能会花费数十亿美元!看到了,去过那里...
  • 作为 64 位数据类型,double 不能代表 64 位整数值的完整精度,因为它还需要为指数部分留出空间。
  • 将“每个计算机科学家都应该了解的浮点知识”打入您最喜欢的搜索引擎。
  • @DavidSchwartz 如果您能在此处提供实际链接,我会很好:"what every computer scientist should know about floating point"
  • 您将整数值分配给double - 我的猜测是您实际上希望将按位等效值分配为double,在这种情况下您将需要使用reinterpret_cast正如 Zak 所建议的那样。

标签: c++ double hex uint64


【解决方案1】:

您正在使用 64 位值来初始化一个 double,它只包含 53 个有效位。有一点舍入,剩下的就丢了。

【讨论】:

  • 看来他有双精度的十六进制表示,并希望将其存储在双精度中。
  • @rcgldr 我看不出问题的任何地方都暗示了这一点。
  • 他具体说明了他期望的输出,即他分配给 dbl 的相同 64 位数字。
【解决方案2】:

如果你只是想做一个 memcpy 风格的交易,你可以试试:

uint64_t x = 0xFEDCBA9876543212;
double dbl = *reinterpret_cast<double *>(&x);

另外,您的测试可能没有按照您的意愿进行:

我的测试:

#include <cstdint>
#include <cstdio>

int main (void) {
  // Move the underlying hex value through multiple types
  uint64_t x = 0xFEDCBA9876543212;
  double dbl = *reinterpret_cast<double *>(&x);
  uint64_t y = *reinterpret_cast<uint64_t *>(&dbl);

  // Check integrity of the result
  printf("dbl: %llX\n", (uint64_t)dbl);  //your test
  printf("x: %llx\ny: %llx\n", x, y);  //my test

  return 0;
}

输出:

dbl: 8000000000000000
x: fedcba9876543212
y: fedcba9876543212

如您所见,底层二进制值在从 x 传递到 dbly 时保持不变,即使您当前的测试 printf("dbl: %llX\n", (uint64_t)dbl); 产生了意外的输出。

【讨论】:

  • 如何在 C 中做同样的事情?
  • @Noah: double dbl = *(double *)&amp;xuint64_t y = *(uint64_t *)&amp;dbl
【解决方案3】:

如果你想准确地知道你的双精度值,那么使用双精度的十六进制格式,

0x1.01234567898abcp-12

然后在另一端组装好号码后用printf("%p", number); 打印号码。如果您的位数正确,则该数字应与输入相匹配。

【讨论】:

    【解决方案4】:

    double precision is 53 bits,这就是你在剩余位置上得到零的原因。

    【讨论】:

    • 不,不固定。我所说的位是隐藏的,与标志分开存在。
    【解决方案5】:

    除了接受的答案,还可以使用联合

    union
    {
        long long _double_exact;
        double _double;
    };
    double_exact = 0xFEDCBA9876543212;
    

    【讨论】: