【问题标题】:How do you output binary representation of floats?你如何输出浮点数的二进制表示?
【发布时间】:2010-10-02 22:11:54
【问题描述】:

我是编程新手,我做过网络开发,但我目前正在尝试学习真正的编程。我的问题已经回答here

union ufloat {
  float f;
  unsigned u
};

ufloat u1;
u1.f = 0.3f;

我不明白它是如何工作的。 0.3 部分有什么作用?我在我的文字中找不到它。这如何将浮点数转换为二进制数?因为cout<<u1.u; 似乎没有给我答案。有人可以帮忙吗?

【问题讨论】:

    标签: c++ binary floating-point


    【解决方案1】:

    0.3 只是一个测试值。打印u1.u 不会为您提供二进制表示,而是将二进制表示的值解释为基数为 10 的整数。要获取二进制值,必须将convertu1.u转为二进制。

    进行转换的另一种方法是使用bitwise operators

    例如:

    unsigned x = 11;
    do
    {
        cout << (x & 1); // print last bit
        x = x >> 1; // get rid of the printed bit
    } while ( x );
    

    请注意,这将以相反的顺序打印位(最低有效位在前)。我将由您来解决这个问题(您可以使用递归或将值存储在数组中,然后将数组反转打印)。

    我还建议您阅读有关unions 的信息。基本上,unsigned 将占用与float 相同的内存空间,允许您绕过使用按位运算符查找float 的二进制表示的限制。

    【讨论】:

    • 以正确的顺序打印位的方式“留作练习”有点便宜。这里的家伙可能比练习更想要答案。
    • @zneak - 因为他已经在处理联合,我认为可以肯定地假设他也知道数组是什么,甚至可能是递归,在这种情况下,我的简短解释就绰绰有余了。如果不是这种情况,那就是 cmets 的用途:他可以告诉我,我可以改进我的帖子。这个问题似乎更多地是关于联合“魔法”的工作原理,而不是如何将整数转换为二进制。
    • 顺便说一句,读取十六进制通常比读取二进制更容易(二进制字符串非常长且单调)。除非您对二进制字符串有特定要求,否则std::cout &lt;&lt; std::hex &lt;&lt; x; 比大量的位旋转更简洁,并且仍然向您显示浮点数的表示。
    【解决方案2】:

    答案在于联合在 C/C++ 中的工作方式。联合允许您使用内存中的相同空间来表示多种类型的数据。因此,在您的示例中,ufloat 联合将浮点数和整数存储在同一内存空间中。根据您访问此内存空间的方式(通过f 数据成员或u 数据成员),程序将分别将内存区域解释为浮点数或无符号整数。

    当您通过u 数据成员访问内存区域时,程序认为您希望将内存区域表示为二进制整数,而不是浮点值。但是由于内存区域实际上存储了一个浮点值(0.3f),它只是简单地输出这个值,就好像它是一个二进制整数一样。因此,您得到了浮点数的二进制表示。

    【讨论】:

      【解决方案3】:

      过于迂腐,那不是有效的 C 或 C++。

      我怀疑现有的每个编译器都支持它,但就标准而言,编写联合的一个成员然后读取另一个成员是无效的。但是,即使知道floatunsigned 的大小相同,您已经在使用一些实现定义的信息,所以您不妨使用更多。这很常见,而且通常有效。

      不过,作为参考,您始终可以将内存视为一系列字节:

      #include <iostream>
      #include <iomanip>
      #include <climits>
      #include <cassert>
      
      int main() {
          float f = 0.3;
          unsigned char *buf = (unsigned char*)(&f);
      
          // Now we just have to print the sucker.
      
          assert(CHAR_BIT == 8); // otherwise hex isn't much use
      
          // This shows the byte representation, low addresses on the left.
          // On a little-endian machine, you might like to count down for 
          // convenience of reading.
          for (int i = 0; i < sizeof f; ++i) {
              std::cout << std::hex << std::setw(2) << std::setfill('0');
              std::cout << static_cast<unsigned int>(buf[i]) << ' ';
          }
          std::cout << '\n';
      }
      

      输出(在我的机器上):

      9a 99 99 3e
      

      如果您更喜欢使用unsigned 而不是unsigned char

      #include <cstring>
      
      float f = 0.3;
      unsigned u;
      assert(sizeof f == sizeof u);
      std::memcpy(&u, &f, sizeof f);
      
      std::cout << std::hex << u << "\n";
      

      输出(在我的机器上):

      3e99999a
      

      【讨论】:

        猜你喜欢
        • 2017-06-16
        • 2016-05-01
        • 1970-01-01
        • 2016-01-01
        • 2015-12-02
        • 2018-04-10
        • 1970-01-01
        • 1970-01-01
        • 2018-10-11
        相关资源
        最近更新 更多