比特流浮动类型强制

时间:2010-02-18 19:22:44

标签: c++ c casting bit-manipulation coercion

我无法让以下代码正常运行。使用在线IEEE-754转换器,我(手动)写出了testData.txt文件,该文件使用应该表示浮点数75.5的位串读取;实际的cout.write确实显示了位字符串也是我所期望的。但是,当我尝试使用union将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

我有什么基本的东西可以使这项工作正常吗?

2 个答案:

答案 0 :(得分:4)

你的联盟需要包含一个char数组而不是一个指针。

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

然后你还要担心字节序;是c [0]浮点数的指数端,或尾数的尾部。 (答案取决于您的硬件 - 英特尔与PPC或SPARC或......)

答案 1 :(得分:3)

您正在使用bitset的构造函数将ASCII转换为位。这会导致您的解码位位于bitset对象而不是union。要从bitset中获取原始位,请使用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的保证较少,实际上这个技巧难以为32提供便携性。具有64位FPU的位机。

编辑:现在我已经使联盟的成员大小相等,我看到这段代码对字节序很敏感。解码后的float将位于big-endian机器上数组的最后一个元素中,即little-endian上的第一个元素。 :v(。也许最好的方法是尝试给联盟的整数成员提供与FP成员完全相同的位数,并在获得to_ulong后执行缩小强制转换。很难保持可移植性标准你好像是用原始代码拍摄的。