【问题标题】:Print binary representation of a float number in C++ [duplicate]在 C++ 中打印浮点数的二进制表示
【发布时间】:2010-11-18 22:46:23
【问题描述】:

可能重复:
Float to binary in C++

我想在 C++ 中打印出浮点数的二进制表示。不是很实用,只是出于好奇。

以下程序无法编译。 reinterpret_cast 失败。我可以使用哪种类型的演员来完成“ &(1

#include <iostream>
using namespace std;


void toBinary(float num) {
  int numi = reinterpret_cast<int>(num);
  cout << num << " " << numi << endl;
  for (int i = 0; i < 8 * sizeof(num); i++){
    if (numi & (1<<i)) {
      cout << 1;
    } else {
      cout << 0;
    }
  }
  cout << endl << endl;
}

int main() {
  float a;
  cout << sizeof(int) << " " << sizeof(float) << endl;
  a = 13.5;
  toBinary(a);
  toBinary(13.9);
  toBinary(2 * a);
  toBinary(-a);
}

【问题讨论】:

    标签: c++ floating-point


    【解决方案1】:

    使用联合。我做了这段代码来做你想做的事:

    // file floattobinary.cc
    #include <string>
    #include <inttypes.h> // for uint32_t
    using namespace std;
    
    void floatToBinary(float f, string& str)
    {
        union { float f; uint32_t i; } u;
        u.f = f;
        str.clear();
    
        for (int i = 0; i < 32; i++)
        {
            if (u.i % 2)  str.push_back('1');
            else str.push_back('0');
            u.i >>= 1;
        }
    
        // Reverse the string since now it's backwards
        string temp(str.rbegin(), str.rend());
        str = temp;
    }
    

    下面是运行这个功能的测试程序:

    // file test.cc
    #include <iostream>
    #include <string>
    #include <cstdlib> // for atof(3)
    
    using namespace std;
    
    void floatToBinary(float, string&);
    
    int main(int argc, const char* argv[])
    {
        string str;
        float f;
        if (argc > 1)
        {
            f = static_cast<float>(atof(argv[1]));
            floatToBinary(f, str);
        }
        cout << str << endl;
        return 0;
    }
    

    编译并运行(我在 Linux 上使用 GNU g++):

    me@mypc:~/college/c++/utils$ g++ -c floattobinary.cc
    me@mypc:~/college/c++/utils$ g++ -c test.cc
    me@mypc:~/college/c++/utils$ g++ -o test *.o
    me@mypc:~/college/c++/utils$ ls
    floattobinary.cc  floattobinary.o  test*  test.cc  test.o
    me@mypc:~/college/c++/utils$ ./test 37.73
    01000010000101101110101110000101
    me@mypc:~/college/c++/utils$ ./test 2.0
    01000000000000000000000000000000
    me@mypc:~/college/c++/utils$ ./test 0.0
    00000000000000000000000000000000
    me@mypc:~/college/c++/utils$ ./test 237.74
    01000011011011011011110101110001
    me@mypc:~/college/c++/utils$ ./test 2.74e12
    01010100000111110111110100101111
    me@mypc:~/college/c++/utils$ ./test 2.74e13
    01010101110001110101110001111010
    me@mypc:~/college/c++/utils$ ./test -88.37
    11000010101100001011110101110001
    

    【讨论】:

    • 这是一个有趣的解决方案。唯一的问题是如果 sizeof(float) != sizeof(uint32_t)。 char* 解决方案没有这个问题。
    • 我认为这是一种未定义的行为。任何时候只有一名工会成员处于活动状态。 SO上有很多关于这个的主题
    • @Ignite:根据 IEEE-754,C/C++ 单精度浮点(浮点类型)的大小为 32 位(4 字节)。 C/C++ 双精度是 64 位(8 字节)。但是,是的,如果 sizeof(float) != sizeof(uint32_t),我的代码将不起作用,这是正确的。请注意,我使用 uint32_t(一个无符号的 32 位数字),因为 int、short、long 等的大小都可以根据架构/编译器/等而改变。 @Chubsdad:不是未定义的行为-C/C++ 中的联合只是将多种类型的对象放置在同一内存地址的一种方式。试试我的代码——它有效。
    • @pr1268 请记住,未定义行为的可能结果之一是似乎正常工作。近年来,编译器编写者一直在使用未定义的行为来获得代码中的最后一点优化。昨天有效的东西明天可能就无效了。
    【解决方案2】:

    有一个更简单的方法。获取一个指向浮点数的指针,并将其重新解释为指向 char 的指针。现在遍历 sizeof(float) 并将每个字符转换为 8 个二进制数字。这种方法也适用于双打。

    【讨论】:

    • 这不违反严格的别名吗?
    • 否,因为char* 被排除在严格的别名规则之外。 (必须有某种方法来获取对象中的字节。)
    • 字节序是否在浮点中起作用?
    • @edA-qa mort-ora-y,是的,字节序会影响结果——我应该指出这一点。从头向下而不是从头向上很容易解决此问题。
    • 循环遍历 sizeof(float) 并转换每个字符是什么意思? 32*8 二进制数 ?不要太多:)?
    猜你喜欢
    • 2018-10-11
    • 2017-06-16
    • 2013-08-22
    • 2016-05-01
    • 2018-04-10
    • 2016-01-01
    • 2015-12-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多