【问题标题】:Fixed-size floating point types固定大小的浮点类型
【发布时间】:2011-02-01 06:09:27
【问题描述】:

stdint.h (C99)、boost/cstdint.hppcstdint (C++0x) 标头中,除其他外,还有 int32_t 类型。

是否有类似的固定大小浮点类型? float32_t 之类的东西?

【问题讨论】:

  • 你为什么需要这样的东西?
  • 当您有一个带有浮点值的数据结构并且您还想知道它的确切大小时,您需要类似的东西。
  • @mobrule:如果您只需要知道大小是多少,请使用sizeof 运算符。当算法要求它是已知的特定大小时,这样的类型会很有用。
  • @Stephen Canon - 是的,当你想保证大小时。比如说,你的数据结构的一个实例将适合 64 位,并且可以按值传递给某个外部库。
  • @StephenCanon 考虑一个跨平台的序列化库。如何使用sizeof 来解决一致地编组和解组浮动类型的问题?

标签: c++ c boost floating-point


【解决方案1】:

目前 C 或 C++ 标准中不存在这样的内容。事实上,甚至无法保证float 将是二进制浮点格式。

一些编译器保证float 类型将是IEEE-754 32 位二进制格式。有些没有。实际上,float 实际上是大多数非嵌入式平台上的 IEEE-754 single 类型,尽管一些编译器以更广泛的格式评估表达式的常见警告适用。

有一个工作组正在讨论为 IEEE-754 的 2008 修订版添加 C 语言绑定,可以考虑建议添加这样的 typedef。如果这被添加到 C 中,我希望 C++ 标准会效仿......最终。

【讨论】:

  • 不管 IEEE-754 与否,它仍然无法防止字节序可移植性问题。
  • @Pietro:更改语言不会影响您的硬件兼容性,它只会排除某些硬件的合规性。 IEEE FP 保证如何帮助可移植性?
  • @Potatoswatter:它将鼓励硬件供应商提供合规的解决方案。如果 a 部分支持标准 C 而不需要软浮点库 hack,而 b 部分不支持,这对 a 部分来说是一个市场优势。
  • @Potatoswatter:(几乎)没有人关心硬件的速度。我们关心软件在硬件上运行的速度。如果软件运行的硬件符合标准并且软件不需要根据运行的平台检测和修补 15 种不同的特殊情况,软件会更快。
  • 您究竟如何通过阻止您的代码在多种利基架构上编译来获得更好的可移植性?您要么依赖浮点数作为 IEEE,在这种情况下,您的代码将已经在每个符合 IEEE 的实现上运行,而不是其他任何东西,或者您不依赖,在这种情况下,您的代码将在更广泛的范围内运行的系统。如果 C++保证 IEEE 合规性,您的代码不会神奇地变得更便携,您只需排除它可能永远在那些不合规的架构上运行。你的逻辑完全倒退了。
【解决方案2】:

如果您想知道您的float 是否为 IEEE 32 位类型,请查看std::numeric_limits<float>::is_iec559。它是编译时常量,而不是函数。

如果您想更加防弹,还请检查std::numeric_limits<float>::digits 以确保他们没有偷偷地使用float 的IEEE 标准双精度。应该是 24。

当涉及到long double,检查digits 更为重要,因为有几种 IEEE 格式可能是合理的:128 位(数字 = 113)或 80 位(数字 = 64)。

float32_t 这样的做法是不切实际的,因为您通常希望使用浮点硬件(如果可用),而不是依赖软件实现。

【讨论】:

  • OS X(32 位和 64 位 Intel)上的 long double 格式正是以小端顺序存储的 IEEE-754 双扩展格式。一点也不时髦。字节 0-7 保存有效位字段,字节 8 和 9 保存指数和符号字段。
  • @Stephen:这是个好消息 :v) 。这与我发布的数字一致吗?
  • 请记住,双扩展(与其他 754 格式不同)具有显式的前导有效位,因此 5.0L 的有效位为 a000000000000000。它的无偏指数为+2,双扩展指数偏差为3fff,所以5.0L的有偏指数为4001。以 little-endian 顺序存储时的实际字节模式是 00 00 00 00 00 00 00 a0 01 40,如果您将其视为两个 little-endian 64 位整数,您将看到您所观察到的确切内容。
  • (*) 英特尔在硬件中实现的双重扩展,即。双扩展格式实际上并没有像 IEEE-754 (1985) 的其他两种基本格式那样固定。
  • @Stephen:我很确定 little-endian 中的 400101 40 00 00 ... 如果不出意外,最不重要的字节首先出现。我确实希望序列a0 01 40 出现在数字中的某个位置(如果它们只执行轮换),但我认为您没有解释为什么a001 40 完全分开。
【解决方案3】:

如果您认为使用诸如 float32_t 和 float64_t 之类的 typedef 出于任何原因是不切实际的,那么您一定是太习惯于您熟悉的操作系统、编译器,以至于您无法在自己的小窝外看太多。

存在本地运行 32 位 IEEE 浮点运算的硬件和其他运行 64 位的硬件。有时这样的系统甚至必须相互通信,在这种情况下,了解每个平台上的 double 是 32 位还是 64 位非常重要。如果 32 位平台要根据来自其他平台的 64 位值进行过多的计算,我们可能希望根据时序和速度要求转换为较低的精度。

除非我确切地知道它们在我的平台上有多少位,否则我个人对使用浮点数和双精度数感到不舒服。如果我要通过某种通信渠道将这些转移到另一个平台,那就更是如此了。

【讨论】:

  • “我个人对使用浮点数和双精度数感到不舒服,除非我确切地知道它们在我的平台上有多少位。如果我要通过某种通信渠道将它们转移到另一个平台,更是如此。” - 你的意思是你使用文本文件格式?有了这些,文件大小就有一个缺点:32 个浮点数需要 4 个字节;这些以文本形式只能代表一个四位数字...
【解决方案4】:

目前有一个提议将以下类型添加到语言中:

decimal32
decimal64
decimal128

有一天可以通过#include <decimal> 访问。

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3871.html

【讨论】:

  • 当然,十进制类型不是 IEEE 754 浮点类型。
  • 等等!我们还需要decimal24 来简化读取 24 位样本的 wav 文件等操作!
猜你喜欢
  • 2011-07-11
  • 2017-09-29
  • 2019-01-11
  • 1970-01-01
  • 1970-01-01
  • 2021-06-25
  • 2017-01-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多