【问题标题】:How to output IEEE-754 format integer as a float如何将 IEEE-754 格式整数输出为浮点数
【发布时间】:2010-12-23 19:26:35
【问题描述】:

我有一个无符号长整数值,它表示使用 IEEE-754 格式的浮点数。在 C++ 中将其打印为浮点数的最快方法是什么?

我知道一种方法,但我想知道 C++ 中是否有更好的便捷实用程序。

我知道的方式示例是:

union
{
    unsigned long ul;
    float f;
} u;

u.ul = 1084227584; // in HEX, this is 0x40A00000

cout << "float value is: " << u.f << endl;

(这会打印出 "float value is: 5" )

【问题讨论】:

    标签: c++ ieee-754 data-conversion


    【解决方案1】:

    swegi 有正确的方向,但错过了一个字符。正确的做法是

    long l = 1084227584L
    float f = reinterpret_cast<float&>(l);
    

    【讨论】:

      【解决方案2】:

      编辑:我以前认为这“很讨厌”,但结果比我想象的要糟糕 - 有关详细信息,请参阅 cmets。我不推荐这种方法,但我把它留在这里是为了记录这种可能性(以及警告!)


      你可以使用指针:

      long ul = 1084227584;
      float* fp = (float*) &ul;
      float f = *fp;
      

      (这可以浓缩成一行,但我认为不这样做更清楚。)

      基本上和你的 union 一样...而且同样狡猾,除非你确定所涉及的类型的大小。

      如果您的平台支持它们,您可能应该为整数和浮点类型使用特定于大小的类型名称。

      【讨论】:

      • 实际上,无论大小如何,它都取决于实现。这比未定义但仍然不好的联合技巧要好。
      • 坏主意。这违反了 C99 严格的别名规则,并且激进的优化编译器可能会产生不正确的结果。见cellperformance.beyond3d.com/articles/2006/06/…
      • 谢谢 - 我认为这很不愉快,但实际上在尺寸合适时不会损坏。编辑以使这一点更清楚,谢谢。如果您认为完全删除答案是个坏主意,请告诉我 - 我很乐意提供帮助。
      • 我会把它留在里面——尽管它是错误的,但使用指针进行类型双关是一种常见的技术。许多编译器不遵循严格的别名规则(哎呀,标准 10 年后甚至没有一个完全符合 C99 的编译器),但仍然值得了解。
      • 真的很迂腐:从这个意义上说,新的“严格别名规则”是程序员的规则,而不是编译器的规则。所有编译器都遵循规则,只是大多数编译器没有利用它们来应用所有可能的优化。但是你可以成为一个符合标准的编译器,只要假设任何两个指针,任何类型,都可能是别名。
      【解决方案3】:

      您建议的联合方法是大多数人会采取的通常路线。但是,在 C/C++ 中从技术上未定义的行为 从联合中读取与最近编写的成员不同的成员。尽管如此,它在几乎所有编译器中都得到了很好的支持。

      将指针转换为Jon Skeet suggested 是一个坏主意——这违反了C 的strict aliasing 规则。激进的优化编译器会为此生成不正确的代码,因为它假定unsigned long * 和@ 类型的指针987654324@ 永远不会互为别名。

      就标准合规性(即不调用未定义的行为)而言,最正确的方法是通过 char* 进行强制转换,因为严格的别名规则允许 char* 指针为任何其他指针的别名类型:

      unsigned long ul = 0x40A00000;
      float f;
      char *pul = (char *)&ul;  // ok, char* can alias any type
      char *pf = (char *)&f;    // ok, char* can alias any type
      memcpy(pf, pul, sizeof(float));
      

      虽然老实说,我还是会选择联合方法。从上面的 cellperformance.com 链接:

      这是一个非常常见的习惯用法,并且得到所有主要编译器的良好支持。实际上,以任何顺序对工会的任何成员进行读写都是可以接受的做法。

      【讨论】:

      • 哇,我没有意识到别名会导致问题。感谢分享!
      • 'float' 不能保证表示为 IEEE-754,因此使用任何形式的转换将 IEEE754 的字节数组转换为浮点数仍然是未定义的。
      【解决方案4】:

      我和 Jon Skeet 有同样的想法,但他抢先了我。不过,我会比他做得更简洁一些。

      cout << "float value is: " << *((float *) &ulValue)) << endl;
      

      您得到一个指向 unsigned long 的指针,然后将其重新解释为指向 float 的指针,然后解除对 float 的指针的引用会产生 float 值。

      由于您是在 C++ 中执行此操作,因此使用 reinterpret_cast 代替旧的 C 样式转换会更清楚。

      cout << "float value is: " << *(reinterpret_cast<float *>(&ulValue)) << endl;
      

      【讨论】:

        【解决方案5】:

        它只适用于 32 位机器或 sizeof(long) == sizeof(float) 的机器。在现代机器上,您可能希望使用 int 来代替......如果您正在执行此技巧,您真的必须小心。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-08
          • 1970-01-01
          • 2016-04-02
          • 1970-01-01
          • 2011-01-25
          相关资源
          最近更新 更多