1

次のコードを正しく動作させるのに問題があります。オンラインの IEEE-754 コンバーターを使用して、浮動小数点数 75.5 を表すビット文字列が読み取られる te​​stData.txt ファイルに (手動で) 書き出しました。実際の cout.write は、ビット文字列も期待どおりであることを示しています。ただし、ユニオンを使用して char* を float に強制しようとすると (この変換を行う典型的な方法であることがわかりました)、結果の float は期待した数値ではありません。

#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

これを正しく機能させるために、私が行っていない基本的なことはありますか?

4

2 に答える 2

4

共用体には、ポインタではなく char の配列を含める必要があります。

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

また、エンディアンについても心配する必要があります。c[0] は float の指数の終わり、または仮数の末尾です。(答えはハードウェアによって異なります - Intel 対 PPC または SPARC または ...)

于 2010-02-18T19:27:20.637 に答える
3

のコンストラクターを使用して ASCII をビットに変換していますbitset。これにより、デコードされたビットbitsetunion. ビットセットから生のビットを取得するには、次の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 ビット マシンに移植するのが困難です。

編集:ユニオンのメンバーを同じサイズにしたので、このコードはエンディアンに敏感であることがわかります。デコードされfloatたものは、ビッグ エンディアン マシンでは配列の最後の要素になり、リトル エンディアンでは最初の要素になります。:v( . おそらく、共用体の整数メンバーに FP メンバーとまったく同じビット数を与え、 を取得した後にナローイング キャストを実行するのが最善の方法でしょうto_ulong。移植性の基準を維持するのは非常に困難です。元のコードで。

于 2010-02-18T19:44:16.927 に答える