4

float の他の型への変換とキャストを使用していくつかのテストを実行しようとしていますが、float 変数を異なる nan の値に設定したいと考えています。

「IEEE 浮動小数点標準の単精度 (32 ビット) NaN のビット単位の例は次のようになります: s111 1111 1axx xxxx xxxx xxxx xxxx xxxx ここで、s は符号 (アプリケーションではほとんどの場合無視されます) であり、a は型を決定します。 NaN であり、x は追加のペイロードです (ほとんどの場合、アプリケーションでは無視されます)。a = 1 の場合、それはクワイエット NaN です。a がゼロで、ペイロードがゼロ以外の場合、それはシグナリング NaN です。"

基本的に、表現のペイロードまたは xxxx を設定する方法を見つけたいと思っています。cでこれを行う方法はありますか?

4

3 に答える 3

8

nan適切な文字列を C99 , nanf,nanl関数に渡すことで「ペイロード」ビットを制御できる場合がありますが、これらはquiet NaNのみを生成し、文字列の解釈は指定されていません (ほとんどの実装では、16 進数として扱われます)。

または、共用体を使用します。

#ifndef __STDC_IEC_559__
#error "This program requires IEEE floating point arithmetic"
#endif

#include <stdint.h>
#include <assert.h>

static_assert(sizeof(float) == sizeof(uint32_t),
    "This program requires float to be 32 bits exactly");

float nanf_with_payload_bits(uint32_t payload)
{
   if (payload & 0x7FA00000) abort();

   union ieee_single {
       float f;
       uint32_t i;
   } nan;

   nan.i = 0x7FA00000 | payload;
   return nan.f;
}

両方の型がまったく同じサイズの場合、共用体の 1 つのメンバーに書き込み、次に別のメンバーから読み取ると、C99+errata で未定義の動作が引き起こされることはありません。( C89 では未定義の動作でしたが、ほとんどのコンパイラは、期待どおりの動作を行うように定義しています。C++ ではまだ未定義の動作である可能性がありますが、よくわかりません。ただし、繰り返しになりますが、ほとんどのコンパイラでは、期待どおりの動作を行うように定義されています。 )

この関数を使用してシグナリングNaN を作成する場合は、その動作が C99/C11 Annex F で明示的に未定義のままになっていることに注意してください。

i共用体のコンポーネントをビットフィールドを持つ構造に分解しようとしないでください。構造内のビット フィールドのメモリ レイアウトは、部分的に実装で定義され、部分的に指定されていません。特に、一連のビット フィールドは必ずしも CPU のエンディアンと同じ順序でワードにパックされるとは限りません (実際には、適切にパックされます)。まったく)。


標準の引用 (すべて C99):

  • この共用体の使用は規定の動作にすぎません: 6.2.6.1p7; J.1
  • 構造内のビットフィールドのレイアウトは予測できません: 6.2.6.1p1,2; 6.7.2.1p10,11,13; J.3.9
  • シグナリング NaN の動作は定義されていません: F.2.1
于 2012-04-28T16:27:12.257 に答える
4

使用memcpy

int32_t i = 0x7FC00000;
float f;
memcpy(&f, &i, sizeof(f));

それを主張することもできsizeof(f) == sizeof(i)ますが、フロートがIEEEであることがわかっている場合は、おそらく基本タイプのサイズも知っているはずです。

于 2012-04-28T16:53:13.077 に答える
3

C で quiet NaN のペイロードを書き込む方法がサポートされています。

nan、nanf、および nanl 関数 (math.h ヘッダーの、1999 C 仕様のセクション 7.12.11.2) は、文字列を引数として受け入れます。strtof、strtod、および strtold 関数 (stdlib.h ヘッダー、セクション 7.20.1.3 の) は、"NAN(文字シーケンス)" 形式の文字列を受け入れます。fscanf および sscanf 関数は strtod に従います。ただし、文字シーケンスは実装定義の方法で解釈されます。(これは、コンパイラが解釈を指定するドキュメントを提供することになっていることを意味します。一部のコンパイラは、標準のこの要件に従わないでしょう。)

fprintf 関数 (stdio.h、セクション 7.19.6.1) は、printf および sprintf と同様に、浮動小数点形式 (a、e、f、g) で「NAN(文字シーケンス)」形式の文字列を出力する場合があります。標準では、文字シーケンスなしで "NAN" を出力することが許可されているため、これは多くのコンパイラでは機能しません。

解釈は実装定義であるため、移植可能であると期待するべきではありません。これらは通常、デバッグなどの特別な目的を目的としています。

于 2012-05-01T16:06:50.340 に答える