位流到浮点类型强制

发布于 2024-08-22 01:57:00 字数 1331 浏览 11 评论 0原文

我无法让以下代码正常工作。使用在线 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

够运 2024-08-29 01:57:00

您的联合需要包含一个字符数组而不是指针。

union { float f; char c[sizeof(float)]; } float2char;

然后你还必须担心字节顺序; c[0] 是浮点数的指数端,或者是尾数的尾部。 (答案会根据您的硬件而有所不同 - Intel 与 PPC 或 SPARC 或...)

Your union needs to include an array of char rather than a pointer.

union { float f; char c[sizeof(float)]; } float2char;

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 ...)

你如我软肋 2024-08-29 01:57:00

您正在使用 bitset 的构造函数将 ASCII 转换为位。这会导致您的解码位位于 bitset 对象中,而不是 union 中。要从位集中获取原始位,请使用 to_ulong 方法:

#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[ sizeof(unsigned long)/sizeof(float) ];
        unsigned long l;
    } funion;

    funion.l = std::bitset<32>( std::string( buffer ) ).to_ulong();
    std::cout << "funion.f = " << funion.f[0]
       << " bits = " << std::hex <<funion.l << std::endl;

    inputFile.close();
    return 0;
}

这通常假设您的 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 the bitset object rather than the union. To get raw bits out of a bitset, use the to_ulong method:

#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[ sizeof(unsigned long)/sizeof(float) ];
        unsigned long l;
    } funion;

    funion.l = std::bitset<32>( std::string( buffer ) ).to_ulong();
    std::cout << "funion.f = " << funion.f[0]
       << " bits = " << std::hex <<funion.l << std::endl;

    inputFile.close();
    return 0;
}

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 for double, 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 getting to_ulong. Very difficult to maintain the standard of portability you seemed to be shooting for in the original code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文