简体   繁体   English

如何输出IEEE-754格式的整数作为浮点数

[英]How to output IEEE-754 format integer as a float

I have a unsigned long integer value which represents a float using IEEE-754 format. 我有一个无符号长整数值,表示使用IEEE-754格式的浮点数。 What is the quickest way of printing it out as a float in C++? 在C ++中以flo​​at形式打印它的最快方法是什么?

I know one way, but am wondering if there is a convenient utility in C++ that would be better. 我知道一种方法,但我想知道在C ++中是否有一个方便的实用程序会更好。

Example of the way that I know is: 我知道的方式示例如下:

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

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

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

(This prints out "float value is: 5" ) (这打印出“浮动值为:5”)

The union method you suggested is the usual route that most people would take. 你建议的联合方法是大多数人会采用的通常方法。 However, it's technically undefined behavior in C/C++ to read a different member from a union than the one that was most recently written. 但是,在C / C ++中,从联合中读取不同的成员而不是最近编写的成员,在技术上是未定义的行为 Despite this, though, it's well-supported among pretty much all compilers. 尽管如此,它在几乎所有编译器中得到了很好的支持。

Casting pointers, as Jon Skeet suggested , is a bad idea -- that violates the strict aliasing rules of C. An aggressive optimizing compiler will produce incorrect code for this, since it assumes that pointers of types unsigned long * and float * will never alias each other. 正如Jon Skeet建议的那样 ,转换指针是一个坏主意 - 这违反了C的严格别名规则。积极的优化编译器会为此产生错误的代码,因为它假定类型为unsigned long *float *指针永远不会别名彼此。

The most correct way, in terms of standards compliance (that is, not invoking undefined behavior), is to cast through a char* , since the strict aliasing rules permit a char* pointer to alias a pointer of any other type: 在标准合规性方面(即,不调用未定义的行为),最正确的方法是强制转换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));

Though honestly, I would just go with the union method. 老实说,我会选择union方法。 From the cellperformance.com link above: 从上面的cellperformance.com链接:

It is an extremely common idiom and is well-supported by all major compilers. 这是一个非常常见的习惯用语,得到了所有主要编译器的良好支持。 As a practical matter, reading and writing to any member of a union, in any order, is acceptable practice. 实际上,以任何顺序读取和写入工会的任何成员都是可以接受的做法。

EDIT: I previously thought this was "just nasty", but it turns out to be worse than I thought - see the comments for details. 编辑:我之前认为这只是“讨厌的”,但事实证明它比我想象的要糟糕 - 详见评论。 I wouldn't recommend this approach, but I'm leaving it here to document the possibility (and the caveat!) 我不推荐这种方法,但我将它留在这里以记录可能性(以及警告!)


You can use pointers: 你可以使用指针:

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

(This can be condensed into a single line, but I think it's clearer not to.) (这可以压缩成一行,但我认为更清楚。)

Basically the same thing as your union... and equally dodgy unless you're sure of the sizes of the types involved. 基本上和你的工会一样......除非你确定所涉及类型的大小,否则同样狡猾。

If your platform supports them, you should probably use the size-specific type names for both the integer and floating point types. 如果您的平台支持它们,则应该为整数和浮点类型使用特定于大小的类型名称。

It will only work on 32-bit machines or machines where sizeof(long) == sizeof(float). 它只适用于32位机器或sizeof(long)== sizeof(float)的机器。 On modern machines you might want to use int instead ... and you really have to take care if you're performing this trick. 在现代机器上你可能想要使用int而不是......如果你正在执行这个技巧,你必须要小心。

I was thinking the same thing as Jon Skeet, but he beat me to it. 我和Jon Skeet的想法一样,但他打败了我。 However, I would do it a little more concisely than he did. 但是,我会比他做得更简洁。

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

You get a pointer to your unsigned long, then reinterpret that as a pointer to float, then dereferencing your pointer to float produces the float value. 你得到一个指向unsigned long的指针,然后将其重新解释为指向float的指针,然后取消引用指向float的指针生成float值。

Since you are doing this in C++, it is clearer to use reinterpret_cast instead of the old C-style cast. 由于您是在C ++中执行此操作,因此使用reinterpret_cast而不是旧的C样式转换更清晰。

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

swegi had the right direction, but missed one character. swegi有正确的方向,但错过了一个角色。 The correct way is 正确的方法是

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

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

相关问题 如何检测非 IEEE-754 浮点数,以及如何使用它们? - How to detect non IEEE-754 float, and how to use them? 将位打印为 IEEE-754 浮点数 - Printing bits as IEEE-754 float 检查符号位的位置是否足以确定 IEEE-754 浮点数相对于 integer 字节序的字节序? - Is checking the location of the sign bit enough to determine endianness of IEEE-754 float with respect to integer endianness? 如何将float转换为double(都存储在IEEE-754表示中)而不会丢失精度? - How to convert float to double(both stored in IEEE-754 representation) without losing precision? IEEE-754的浮点数,双精度数和四进制数是否保证精确表示-2,-1,-0、0、1、2? - Does IEEE-754 float, double and quad guarantee exact representation of -2, -1, -0, 0, 1, 2? 添加 IEEE-754 格式的正数和负数 - Adding positive and negative numbers in IEEE-754 format 将 2 uint16_t 转换为 32-float IEEE-754 格式 - Converting 2 uint16_t to 32-float IEEE-754 fomat 32位,64位和80位浮点IEEE-754的可表示值范围? - Range of representable values of 32-bit, 64-bit and 80-bit float IEEE-754? 在C ++中编写符合IEEE-754标准的双/浮点分区的最快方法是什么? - What is the fastest way to write a IEEE-754 compliant double/float division in C++? 如果可以用IEEE 754中的二进制格式表示硬编码是否精确浮动? - Is hardcode float precise if it can be represented by binary format in IEEE 754?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM