21

私がこれをしたい理由を無視して、754 IEEE fp 標準は次の動作を定義していません:

float h = NAN;
printf("%x %d\n", (int)h, (int)h);

Gives: 80000000 -2147483648

基本的に、NAN の値に関係なく、80000000 (16 進数) または -2147483648 (10 進数) が出力されます。これには理由がありますか、および/またはこれは正しい動作ですか? もしそうなら、どうしてですか?

NaN のさまざまな値を指定する方法は次のとおり です。NaN に相当する float のビット値を手動で設定するにはどうすればよいですか?

基本的に、NaN のペイロードがキャストの出力に影響する場合はありますか?

ありがとう!

4

3 に答える 3

16

浮動小数点数の整数へのキャストの結果は、整数変数の範囲外の値(切り捨ての場合は±1)に対して未定義/未指定です。

6.3.1.4項:

実際の浮動小数点型の有限値が以外の整数型に変換されると_Bool、小数部は破棄されます(つまり、値はゼロに向かって切り捨てられます)。整数部分の値を整数型で表すことができない場合、動作は未定義です。

実装でが定義されている場合、__STDC_IEC_559__浮動小数点型から整数型への変換の場合_BOOL

浮動小数点値が無限大またはNaNの場合、または浮動小数点値の整数部分が整数型の範囲を超える場合、「無効な」浮動小数点例外が発生し、結果の値は指定されません。

(付録F [規範的]、ポイント4)

実装でが定義されていない場合、__STDC_IEC_559__すべての賭けは無効になります。

于 2012-04-28T18:53:32.897 に答える
11

この動作には理由がありますが、通常は信頼できるものではありません。

お気づきのように、IEEE-754 では、浮動小数点 NaN を整数に変換したときに何が起こるかを指定していませんが、コンパイラがおそらく無視する無効な操作の例外を発生させる必要があります。C 標準では、動作が未定義であると述べられています。つまり、得られる整数の結果がわからないだけでなく、プログラムが何を行うのかまったくわかりません。標準では、プログラムを中止したり、クレイジーな結果を得たり、何でもしたりできます。このプログラムはおそらく Intel プロセッサで実行され、コンパイラは組み込み命令の 1 つを使用して変換を行った可能性があります。Intelは命令の動作を非常に慎重に指定しており、浮動小数点NaNを32ビット整数に変換する動作は、NaNのペイロードに関係なく0x80000000を返すことです。これはあなたが観察したものです。

Intel は命令の動作を指定しているため、使用されている命令がわかっている場合はそれを信頼できます。ただし、コンパイラはそのような保証を提供しないため、この命令が使用されていることに依存することはできません。

于 2012-05-01T15:37:40.090 に答える
3

まず、NAN は、IEEE 標準に従って浮動小数点数と見なされないすべてのものです。したがって、それはいくつかの可能性があります。私が使用しているコンパイラには NAN と -NAN があるため、1 つの値だけではありません。

第 2 に、すべてのコンパイラには、isnanこのケースをテストする関数のセットがあるため、プログラマは自分でビットを処理する必要がありません。要約すると、値をのぞいても違いはないと思います。値をのぞいて符号、仮数、指数などの IEEE 構造を確認することもできますが、ここでも、各コンパイラはそれを処理する独自の関数 (より適切にはライブラリ) を提供します。

ただし、あなたのテストについてはもっと言いたいことがあります。

float h = NAN;
printf("%x %d\n", (int)h, (int)h);

あなたが行ったキャストは、intに変換するためにfloatを切り捨てます。float で表される整数を取得する場合は、次のようにします。

printf("%x %d\n", *(int *)&h, *(int *)&h);

つまり、float のアドレスを取得し、それを int へのポインターとして参照し、最終的に int 値を取得します。このようにして、ビット表現が保持されます。

于 2012-04-28T18:58:25.393 に答える