简体   繁体   English

如何输出浮点数的二进制表示形式?

[英]How do you output binary representation of floats?

I am new to programming, I've done web development, but I am currently trying to learn real programming. 我是编程新手,已经完成了Web开发,但是我目前正在尝试学习真正的编程。 The question I have is already answered here . 我的问题已经在这里回答

union ufloat {
  float f;
  unsigned u
};

ufloat u1;
u1.f = 0.3f;

What I don't get is how it works. 我不明白的是它是如何工作的。 What does the 0.3 part do? 0.3部分有什么作用? I couldn't find it in my text. 我在文字中找不到它。 And how does this convert a float to binary? 以及如何将浮点数转换为二进制? Because cout<<u1.u; 因为cout<<u1.u; doesn't seem to give me the answer. 似乎没有给我答案。 Can someone help? 有人可以帮忙吗?

0.3 is just a test value. 0.3只是一个测试值。 Printing u1.u will not give you the binary representation, but the value of the binary representation interpreted as a base 10 integer. 打印u1.u不会为您提供二进制表示形式,而是将二进制表示形式的值解释为以10为底的整数。 To get the binary value, you have to convert u1.u to binary. 要获取二进制值,必须 u1.u 转换为二进制。

Another way you can do the conversion is by using bitwise operators . 进行转换的另一种方法是使用按位运算符

For example: 例如:

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

Note that this will print the bits in reverse order (least significant first). 请注意,这将以相反的顺序打印位(最低有效位在前)。 I'll leave it up to you to fix this (you can use recursion or store values in an array and then print the array reversed). 我将由您自己解决此问题(您可以使用递归或将值存储在数组中,然后反向打印数组)。

I also suggest you read about unions . 我还建议您阅读有关工会的文章 Basically, the unsigned will occupy the same memory space as the float , allowing you to circumvent the restrictions of using bitwise operators to find the binary representation of the float . 基本上, unsigned将占用与float相同的内存空间,从而使您能够规避使用按位运算符查找float的二进制表示形式的限制。

The answers lies in how unions work in C/C++. 答案在于联合在C / C ++中的工作方式。 A union allows you to represent multiple types of data using the same space in memory. 联合允许您使用内存中的相同空间表示多种类型的数据。 So in your example, the ufloat union stores the float and the integer in the same memory space. 因此,在您的示例中, ufloat联合将float和整型存储在同一内存空间中。 Depending on how you access this memory space, (either via the f data member or the u data member), the program will interpret the memory region as either a float or an unsigned integer respectively. 根据您访问此存储空间的方式(通过f数据成员或u数据成员),程序将分别将存储区域解释为浮点数或无符号整数。

When you access the memory region via the u data member, the program thinks you want to represent the memory region as a binary integer, rather than a floating point value. 当您通过u数据成员访问内存区域时,程序认为您希望将内存区域表示为二进制整数,而不是浮点值。 But since the memory region is actually storing a floating point value (0.3f), it simply outputs this value as if it was a binary integer. 但是,由于存储区实际上存储的是浮点值(0.3f),因此仅将其输出为二进制整数即可。 Thus, you get your binary representation of the float. 因此,您将获得浮点数的二进制表示形式。

To be excessively pedantic, that's not valid C or C++. 要过度学究,这不是有效的C或C ++。

I suspect that every compiler in existence supports it, but as far as the standard is concerned, it's not valid to write one member of a union and then read another. 我怀疑现有的每个编译器都支持它,但是就标准而言,先编写一个联合成员然后再读取另一个成员是无效的。 However, to even know that float and unsigned are the same size you're already using some implementation-defined information, so you may as well use more. 但是,要知道floatunsigned是相同的大小,您已经在使用一些实现定义的信息,因此您也可以使用更多的信息。 It's common and it generally works. 这很常见,而且通常可以正常工作。

For reference, though, you can always examine memory as a series of bytes: 作为参考,您始终可以将内存检查为一系列字节:

#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';
}

Output (on my machine): 输出(在我的机器上):

9a 99 99 3e

If you do prefer to use unsigned rather than unsigned char : 如果您确实喜欢使用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";

Output (on my machine): 输出(在我的机器上):

3e99999a

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM