【问题标题】:C++ declare platform independent 32-bit floatC++ 声明独立于平台的 32 位浮点数
【发布时间】:2013-09-13 08:28:07
【问题描述】:

有没有办法在 C++ 中声明 32 位浮点值 - 确保无论平台/编译器如何,它始终是 32 位?

我可以对这样的整数做到这一点:

#include <stdint.h>

uint32_t var;  //32 bit unsigned integer
uint64_t var1; //64 bit unsigned integer

有没有办法为花车做类似的事情?据我所知,

float var; //Usually is 32 bit, but NOT GUARANTEED to be 32 bit

是特定于实现的,不一定是 32 位的。(如果我错了,请纠正我)。

我正在使用 qt,所以如果有任何使用它的解决方案,我会接受它 - 我找不到类似 quint16 的浮点数(qreal 会根据平台更改大小)。

【问题讨论】:

  • 否 - 某些平台可能有十进制浮点数。
  • 如果平台不支持 32 位二进制浮点数据类型,您将如何处理?
  • 那么,如果float 不是 32 位,您究竟希望发生什么?当然可以检查if (sizeof(float) != 4 &amp;&amp; CHAR_BITS == 8) PANIC("Not 32-bit float!!!"); - 但如果没有 32 位浮点数,我不确定你希望编译器做什么......
  • 那么,您编写的代码可能会在真正不起眼的硬件上运行吗?我的意思是 DSP 和大型而古老的大型机?如果不是,那么我会说忽略这个问题...... [我感觉 QT 在大型机上无论如何都不能很好地工作,而且 DSP 往往非常专业]。
  • 毫无意义。即使您有两个都是 32 位的浮点数,当一个具有 23 位尾数而另一个具有 25 位尾数时,它们仍然不兼容。您需要指定所有宽度,而不仅仅是总宽度。

标签: c++ qt types floating-point


【解决方案1】:

您正在使用 Qt。这是 C++ 特有的,所以我不确定为什么这个问题被标记为 C。

据我所知,在所有支持 Qt 的平台上,键入 float 是 32 位 IEEE。

如果有人决定将 Qt 移植到具有 64 位 float 的 Cray 向量机上,那么无论如何您都不会拥有 32 位浮点类型(除非您自己在软件中实现它,但我不明白这会有什么用)。

没有&lt;stdfloat.h&gt;/&lt;cstdfloat&gt;对应&lt;stdint.h&gt;/&lt;cstdint&gt;。 C 和 C++ 提供了 floatdoublelong double,并对它们施加了最低要求,但没有为您提供要求任何特定大小的浮点类型的方法。

您最好的选择可能是在main 中添加类似这样的内容,或者在程序启动期间保证调用的某些函数中:

assert(CHAR_BIT * sizeof (float) == 32);

如果你的代码隐式依赖于它,也许还有CHAR_BIT == 8

assert 不太可能触发 - 如果触发了,您将遇到更大的问题。

您可能需要重新考虑是否真的需要 32 位浮点类型。如果您的代码在 64 位 float 的系统上运行,那怎么会无法满足您的要求?

【讨论】:

  • 谢谢!确定 Qt 只能在 32 位 IEEE 上运行吗?我标记为 C,因为我使用 qt 但不限于它 - 任何确保浮点数为 32 位/提供保证为 32 位的浮点数据类型的解决方案都可以,包括 C。我希望浮点数为 32 位,因为我写 32 位,因为我根据数据大小做了一些指针转换/算术运算。
  • @IlyaKobelevskiy:这对我来说不确定,也不太确定会继续如此,但很有可能。考虑不要编写对sizeof (float) 做出任何假设的代码。否则,如果没有可用的 32 位浮点类型,请决定您要做什么。除非您在软件中实现 32 位 FP(这可能是矫枉过正),否则您将不走运——assert 正是处理这种情况的方法。
  • 你也可以进行编译时检查——C++定义了宏FLT_MIN, FLT_MAX, FLT_MANT_DIG (#include &lt;cfloat&gt;);或者在 C++11 代码中,您可以使用 static_assert(numeric_limits&lt;float&gt;::max() &lt;= ...)(或 min 等)(#include &lt;limits&gt;)。
  • 那么float 是 32 位但格式与您想要的格式不同的平台呢?很难说出您的要求是什么。
  • @IlyaKobelevskiy:一些低端 ARM 只有double 64 位 IEEE 硬件。 32 位 FP 可以在 64 位中相当有效地模拟。但是您会遇到类似于 x87 80 位寄存器的问题。
【解决方案2】:

没有这种大小的浮点类型,但您始终可以静态断言大小为 32 位。甚至可能像全局 char 数组这样简单:

#include <climits>

char static_assert_float32[1 - (2 * ((sizeof(float) * CHAR_BIT) != 32))];

如果 float 不是 32 位,则通过声明一个负大小的数组将无法编译。

【讨论】:

  • 或者,更简单地说,static_assert(sizeof(float) == 4, "require 32-bit floats")。
  • @Adam:不,CHAR_BIT==16 失败。
  • @MSalters,如果我没看错,你是对的。如果一个字节不是 8 位,我写的是真的。由于 sizeof 返回字节数。是这个意思吗?
  • @AdamBurry:是的,C++ 将byte 定义为char 的大小,不一定是八位字节(8 位)。因此,根据定义,sizeof(char)==1 无处不在。所有其他尺寸都是相对于此定义的。
  • 嗯,有明显的static_assert(sizeof(float) * CHAR_BIT == 32, "require 32 bits floats",这使得32明显并且代码可移植。
【解决方案3】:

最常见的 C 和 C++ 实现将使用 32 位 float 类型。如果您确实需要捕获任何不会出现这种情况的平台,您可以使用以下方法在程序早期抛出错误:

#include <limits.h>
if (sizeof(float) * CHAR_BIT != 32)
    // error code here

不幸的是,我不知道在编译时检测它的方法,我之前的答案有缺陷。

【讨论】:

  • 据我所知,sizeof() 不能用于预处理指令。
  • @MartinR 为什么不呢?无论如何它是编译时间:p
  • @user9000:因为预处理器在源代码被解析之前就运行了; sizeof 关键字只是一个普通的标识符,没有特殊意义。
  • 我的 clang 编译器报错:“错误:令牌在预处理器子表达式中不是有效的二元运算符”。
  • @MartinR 我相信你是对的。我会更新或删除这个答案。
【解决方案4】:

在支持 IEEE-754 float 的平台上,它将是 32 位的。在没有的平台上,不同的宽度可能是您最不关心的问题。底线 - 使用float,不用担心。

【讨论】:

    【解决方案5】:

    当且仅当 float 符合 IEC 559/IEEE 754 浮点标准时,布尔静态成员常量 std::numeric_limits&lt;float&gt;::is_iec559 为真。您需要#include 标头&lt;limits&gt;

    请注意,仅此一项并不能告诉您 float 是否具体 32 位 IEEE 浮点,只是它是 IEEE 浮点——一些没有 32 位浮点的实现例如,点硬件可能会选择 float 为 64 位 IEEE 浮点数。

    【讨论】:

      【解决方案6】:

      知道 sizeof(float) 为 32 位通常就足够了,但在所有情况下都不够。

      IEEE 758 定义了众所周知的 32 位 binary32,它通常被实现。但是 IEEE 758 也定义了一个 32 位的 decimal32,它主要用于存储而不是计算。还存在其他非 IEEE 758 32 位浮点实现,但肯定不那么常见。

      即使已知float 是 32 位 IEEE 758-2008 binary32,给定环境遵守其严格定义(Nan、次正规、舍入模式)的程度可能会有所不同.我怀疑这是 32-float 实现细微变化的最大来源。

      因此,准确了解所使用的浮点模型的目标可能会确保跨平台的一致性,但在编译时检测可能非常具有挑战性。

      【讨论】:

        猜你喜欢
        • 2011-10-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-18
        • 1970-01-01
        • 2010-10-08
        • 1970-01-01
        • 2011-01-16
        相关资源
        最近更新 更多