在C++中打印浮点数的二进制表示

6

可能是重复问题:
C++中的浮点数转二进制

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

以下程序无法编译。reinterpret_cast失败了。有什么类型的转换可以使用,以便我可以执行“ &(1 << i) ”这一部分吗?

#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);
}
2个回答

19

有一种更简单的方法。取一个指向浮点数的指针,并将其reinterpret_cast为一个指向char的指针。现在循环遍历sizeof(float),并将每个char转换为8个二进制数字。这种方法也适用于双精度浮点数。


6
不行,因为char*符合严格别名规则的例外(必须有某种方式来访问对象中的字节)。 - Fred Foo
1
浮点数中的字节序是否起作用? - edA-qa mort-ora-y
1
@edA-qa mort-ora-y,是的,字节序会影响结果——我应该指出这一点。通过从结尾向下而不是从开头向上遍历,可以轻松解决这个问题。 - Mark Ransom
@Guillaume07,“sizeof”是C++中的一个运算符,它返回“char”元素的大小。“sizeof(float)”应该是“4”,而不是“32”。 - Mark Ransom
@Guillaume07,是的,您可以使用掩码一次获取一个位并单独转换它。原始问题中的代码展示了如何实现这一点。以这种方式,您最终将得到2个循环。 - Mark Ransom
显示剩余3条评论

3
使用联合体。我编写了以下代码,可以完全满足您的需求:
// 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

1
这是一个有趣的解决方案。唯一的问题是如果sizeof(float) != sizeof(uint32_t)。char*解决方案没有这个问题。 - Petko M
2
我认为这是一种未定义的行为。联合中只有一个成员处于活动状态。在SO上有许多关于此问题的线程。 - Chubsdad
1
@Ignite: 根据IEEE-754标准,C/C++单精度浮点数(float类型)的大小为32位(4字节)。C/C++双精度浮点数为64位(8字节)。但是,如果sizeof(float) != sizeof(uint32_t),我的代码将无法工作,你是正确的。请注意,我使用uint32_t(无符号32位数字),因为int、short、long等的大小都可能因架构/编译器等而改变。@Chubsdad: 不是未定义行为-C/C++中的联合体只是一种在同一内存地址上放置多种类型对象的方法。尝试我的代码-它可以工作。 - pr1268
1
@pr1268 请记住,未定义行为的可能结果之一是表现出正确工作。近年来,编译器编写者一直在利用未定义行为,在其代码中获得最后一点优化。昨天可行的方法,明天可能就不行了。 - Mark Ransom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接