4

IEEE-754 形式を使用して float を表す unsigned long integer 値があります。C ++でフロートとして出力する最も簡単な方法は何ですか?

私は 1 つの方法を知っていますが、C++ にもっと便利な便利なユーティリティがあるかどうか疑問に思っています。

私が知っている方法の例は次のとおりです。

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

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

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

(これは "float value is: 5" を出力します)

4

5 に答える 5

7

あなたが提案した結合方法は、ほとんどの人が取る通常のルートです。ただし、C/C++ では、最後に記述されたものとは異なるメンバーを共用体から読み取ることは、技術的に未定義の動作です。それにもかかわらず、ほとんどすべてのコンパイラで十分にサポートされています。

Jon Skeet が提案したように、ポインターのキャストは悪い考えです。これは、C の厳密なエイリアシングunsigned long *ルールに違反します。積極的な最適化コンパイラは、型のポインターを想定し、float *互いにエイリアスを作成しないため、これに対して誤ったコードを生成します。

標準への準拠 (つまり、未定義の動作を呼び出さない) の観点から最も正しい方法は、 を介してキャストすること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));

正直なところ、私はユニオン方式を使用します。上記の cellperformance.com リンクから:

これは非常に一般的なイディオムであり、すべての主要なコンパイラで十分にサポートされています。実際問題として、任意の順序で組合の任意のメンバーに対して読み取りと書き込みを行うことは、許容される慣行です。

于 2009-12-06T20:42:34.710 に答える
3

編集:以前はこれは「ただ厄介」だと思っていましたが、思ったよりも悪いことが判明しました-詳細についてはコメントを参照してください. 私はこのアプローチをお勧めしませんが、可能性を文書化するためにここに残しています (そして警告!)


ポインタを使用できます:

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

(これは 1 行に要約できますが、そうしない方がわかりやすいと思います。)

基本的にあなたの組合と同じこと...そして、関係する型のサイズが確かでない限り、同様に危険です。

プラットフォームがそれらをサポートしている場合は、おそらく整数型と浮動小数点型の両方にサイズ固有の型名を使用する必要があります。

于 2009-12-06T20:17:42.490 に答える
3

32 ビット マシンまたは sizeof(long) == sizeof(float) のマシンでのみ動作します。最新のマシンでは、代わりに int を使用したい場合があります...そして、このトリックを実行する場合は本当に注意する必要があります.

于 2009-12-06T20:20:54.190 に答える
3

私はジョン・スキートと同じことを考えていましたが、彼は私を打ちのめしました。ただし、私は彼よりももう少し簡潔に説明します。

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

unsigned long へのポインターを取得し、それを float へのポインターとして再解釈し、float へのポインターを逆参照すると、float 値が生成されます。

これは C++ で行っているため、古い C スタイルのキャストの代わりに reinterpret_cast を使用する方が明確です。

cout << "float value is: " << *(reinterpret_cast<float *>(&ulValue)) << endl;
于 2009-12-06T20:24:44.180 に答える
1

swegi の方向性は正しかったのですが、1 文字抜けていました。正しい方法は

long l = 1084227584L
float f = reinterpret_cast<float&>(l);
于 2009-12-07T11:14:25.600 に答える