【问题标题】:Ensuring C++ doubles are 64 bits确保 C++ 双精度为 64 位
【发布时间】:2010-10-19 15:13:04
【问题描述】:

在我的 C++ 程序中,我需要从外部字节序列中提取一个 64 位浮点数。有什么方法可以确保在编译时双精度为 64 位?我应该使用其他类型来存储数据吗?

编辑:如果您正在阅读本文并且实际上正在寻找一种方法来确保以 IEEE 754 格式存储,请查看以下 Adam Rosenfield 的答案。

【问题讨论】:

  • 你到底在做什么?您是否正在寻找一种完全可移植的方式来获取 8 个字节并将它们解释为 IEEE 标准的 64 位浮点数?
  • @David:是的,这正是我正在做的。我在某处发现了一些说 C++ 浮点数和双精度数采用 IEEE-754 格式的东西。我不确定双打是否总是使用相同的精度并想为其添加检查。
  • 现在我不确定我的原始信息是否正确。这里有什么约定?我应该删除这个问题并添加另一个关于从 IEEE-754 转换的问题吗?
  • IIUC: 1) IEEE 754 不受标准保证(否则,我看不到 std::numeric_limits::is_iec559 的要点) 2) is_iec559 == true 不保证二进制表示.
  • Eric: numeric_limits::is_iec559 的存在是因为 numeric_limits 被设计为可扩展的,例如,对于 is_iec559==false 的用户定义 BigFloat 类型可能存在 numeric_limits 特化.但是,您是对的,内置浮点数可能不是 IEEE 754。

标签: c++ types precision compiler-construction ieee-754


【解决方案1】:

在 C99 中,您可以检查是否定义了预处理器符号 __STDC_IEC_559__。如果是,那么您可以保证double 将是一个用 IEEE 754(也称为 IEC 60559)格式表示的 8 字节值。请参阅 C99 标准,附件 F。不过,我不确定此符号在 C++ 中是否可用。

#ifndef __STDC_IEC_559__
#error "Requires IEEE 754 floating point!"
#endif

或者,您可以检查预定义常量__DBL_DIG__(应为 15)、__DBL_MANT_DIG__(应为 53)、__DBL_MAX_10_EXP__(应为 308)、__DBL_MAX_EXP__(应为 1024)、__DBL_MIN_10_EXP__ (应该是-307)和__DBL_MIN_EXP__(应该是-1021)。这些应该适用于所有类型的 C 和 C++。

【讨论】:

  • 这是一个比我希望的更好的解决方案。不过,接受了埃文的回答,因为它回答了存在的问题。我只是问错了问题。
【解决方案2】:

如果您需要知道您的 C++ 实现是否支持标准双精度,请查看std::numeric_limits< double >::is_iec559。这不仅保证了总位数为 64,还保证了 double 内所有字段的大小和位置。

【讨论】:

    【解决方案3】:

    对其他答案的改进(假设 char 是 8 位,标准不保证这一点..)。会是这样的:

    char a[sizeof(double) * CHAR_BIT == 64];
    

    BOOST_STATIC_ASSERT(sizeof(double) * CHAR_BIT == 64);
    

    您可以找到在<limits.h><climits> 中定义的CHAR_BIT。

    【讨论】:

    • 嗯,不,它根本没有。 sizeof 以字符为单位返回。 CHAR_BIT 定义为每个字符的位数。将 sizeof(x) 乘以 CHAR_BIT,您就确切地知道 x 有多少位。
    • 例如,在 x86 上 CHAR_BIT 被定义为 8。sizeof(double) 返回 8. (8 * 8) == 64。
    • 引用标准 5.3.3p1:“sizeof 运算符在其操作数的对象表示中产生字节数。” QED
    • 此外,由于 CHAR_BIT 继承自 c,因此适用 c 的规则:引用 C99 草案标准(第 6.2.6.1p3 节):“存储在任何其他对象类型的对象中的值由 nx CHAR_BIT 位,其中 n 是该类型对象的大小,以字节为单位。"
    • 最后,从您引用的同一段中:“sizeof(char), sizeof(signed char) and sizeof(unsigned char) are 1;”如果 sizeof(char) == 1 并且 sizeof 根据定义返回以字节为单位。那么这意味着一个 char is 与一个字节的大小相同。但是,一个字节不必是 8 位。
    【解决方案4】:

    请参阅 this post 了解类似问题和称为 CCASSERT 的非增强编译时断言。

    【讨论】:

      【解决方案5】:

      我认为您不应该关注双精度的“原始大小”(通常是 80 位,而不是 64 位),而应该关注其精度。

      感谢 numeric_limits::digits10,这相当容易。

      【讨论】:

      • 80 位双精度是 Intel 主义,只有当 FPU 实际上处于 80 位模式(也有 64 位模式)时才为真......
      • 甚至是 32 位模式,这取决于您如何初始化 Direct3D。
      【解决方案6】:

      您可以使用Boost static assertions 来执行此操作。查看Use at namespace scope 示例。

      【讨论】:

        【解决方案7】:

        不用boost的解决办法就是这样定义数组

        char a[ 8 == sizeof(double) ];
        

        如果双精度不是 64 位,则代码如下所示

        char a[0];
        

        这是一个编译时错误。只需在此说明附近添加适当的注释即可。

        【讨论】:

        • 一个字节不保证是8位
        • @Evan:有趣的一点。在条件中添加“&& (unsigned char) 255 == 255 && (unsigned char) 256 == 0” 以检查字符是否为 8 位。
        • double 的大小是 16 字节,但字节是 4 位的情况怎么办?
        • @j_random_hacker:最好添加“&& CHAR_BIT == 8”,因为 CHAR_BIT 定义为每个字符/无符号字符的位数。
        • 或者更好的是 "sizeof(double) * CHAR_BIT == 64"
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-02
        • 1970-01-01
        • 2011-02-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多