位流到浮点类型强制
我无法让以下代码正常工作。使用在线 IEEE-754 转换器,我(手动)写入 testData.txt 文件,该文件使用表示浮点数 75.5 的位字符串读取;实际的 cout.write 确实显示该位字符串也符合我的预期。然而,当我尝试使用联合将 char* 强制转换为浮点数时(正如我所看到的,这是完成此转换的典型方法),得到的浮点数不是我期望的数字。
#include<climits>
#include<iostream>
#include<fstream>
#include<bitset>
int main( int, char** )
{
std::ifstream inputFile( "testData.txt", std::ios_base::in | std::ios_base::binary );
if( !inputFile ) std::cout << "Failed to open input file!" << std::endl;
char buffer[ CHAR_BIT * sizeof(float) ];
inputFile.read( buffer, CHAR_BIT * sizeof(float) );
std::cout << "cout.write of input from file = ";
std::cout.write( buffer, CHAR_BIT * sizeof(float) );
std::cout << std::endl;
union { float f; char* c; } fToCharStarUnion;
fToCharStarUnion.c = buffer;
std::bitset< sizeof(float) * CHAR_BIT > bits( std::string( fToCharStarUnion.c ) );
std::cout << "fToCharStarUnion.f = " << fToCharStarUnion.f << " bits = " << bits << std::endl;
inputFile.close();
return 0;
}
运行此命令的返回结果是:
cout.write of input from file = 01000010100101110000000000000000
fToCharStarUnion.f = -1.61821e+38 bits = 01000010100101110000000000000000
是否有一些我没有做的基本操作可以使其正常工作?
I'm having trouble getting the following code to work correctly. Using an online IEEE-754 converter, I wrote out (by hand) to the testData.txt file that is read with the bit string that should signify the floating point number 75.5; the actual cout.write does show that the bit string is as I expect as well. However, when I try to coerce the char* into a float using a union (as I have seen is a typical way to accomplish this conversion) the resulting float is not the number I expect.
#include<climits>
#include<iostream>
#include<fstream>
#include<bitset>
int main( int, char** )
{
std::ifstream inputFile( "testData.txt", std::ios_base::in | std::ios_base::binary );
if( !inputFile ) std::cout << "Failed to open input file!" << std::endl;
char buffer[ CHAR_BIT * sizeof(float) ];
inputFile.read( buffer, CHAR_BIT * sizeof(float) );
std::cout << "cout.write of input from file = ";
std::cout.write( buffer, CHAR_BIT * sizeof(float) );
std::cout << std::endl;
union { float f; char* c; } fToCharStarUnion;
fToCharStarUnion.c = buffer;
std::bitset< sizeof(float) * CHAR_BIT > bits( std::string( fToCharStarUnion.c ) );
std::cout << "fToCharStarUnion.f = " << fToCharStarUnion.f << " bits = " << bits << std::endl;
inputFile.close();
return 0;
}
The return result of running this is:
cout.write of input from file = 01000010100101110000000000000000
fToCharStarUnion.f = -1.61821e+38 bits = 01000010100101110000000000000000
Is there something fundamental I am not doing which will make this work correctly?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您的联合需要包含一个字符数组而不是指针。
然后你还必须担心字节顺序; c[0] 是浮点数的指数端,或者是尾数的尾部。 (答案会根据您的硬件而有所不同 - Intel 与 PPC 或 SPARC 或...)
Your union needs to include an array of char rather than a pointer.
You will also then have to worry about endianness; is c[0] the exponent end of the float, or the tail of the mantissa. (The answer will vary depending on your hardware - Intel vs PPC or SPARC or ...)
您正在使用
bitset
的构造函数将 ASCII 转换为位。这会导致您的解码位位于bitset
对象中,而不是union
中。要从位集中获取原始位,请使用 to_ulong 方法:这通常假设您的 FPU 以与 CPU 的整数部分相同的字节序运行,并且 sizeof(long) > ;= sizeof(float)…对于
double
的保证较少,而且事实上,这个技巧更难移植到具有 64 位 FPU 的 32 位机器上。编辑:既然我已经使联合成员的大小相等,我发现这段代码对字节序很敏感。解码后的浮点数将位于大端机器上数组的最后一个元素,小端机器上的第一个元素。 :v( 。也许最好的方法是尝试为联合体的整数成员提供与 FP 成员完全相同的位数,并在获取
to_ulong
后执行缩小转换。很难维护您似乎在原始代码中追求的可移植性标准。You are translating the ASCII into bits using the constructor of
bitset
. That causes your decoded bits to be in thebitset
object rather than theunion
. To get raw bits out of a bitset, use theto_ulong
method:This generally assumes that your FPU operates with the same endianness as the integer part of your CPU, and that
sizeof(long) >= sizeof(float)
… less guaranteed fordouble
, and indeed the trick is harder to make portable for 32-bit machines with 64-bit FPUs.Edit: now that I've made the members of the union equal sized, I see that this code is sensitive to endianness. The decoded
float
will be in the last element of the array on a big-endian machine, first element on little-endian. :v( . Maybe the best approach would be to attempt to give the integer member of the union exactly as many bits as the FP member, and perform a narrowing cast after gettingto_ulong
. Very difficult to maintain the standard of portability you seemed to be shooting for in the original code.