isnan(), isinf()
はC99まで仕様に含まれていませんでしたが、C89でそのような関数を実装する方法はありますか?
if (d * 0 != 0)
を使用してdがNaNまたはInfであるかどうかを確認できますが、常に:-Werror=float-equal
を叫びたいオプションerror: no == or != on float point value
を使用してプロジェクトをコンパイルします。
では、C89でnanとinfをどのようにチェックするのでしょうか。
システムが IEEE 754 Standard を使用して浮動小数点値を表す場合(ほとんどの場合)、NaN
およびinf
値を明示的にチェックできます。単精度(32ビット)浮動小数点値には1
符号ビット(ビット31)、8 bit
指数(ビット30〜23)および23 bit
仮数(ビット22-0)、そのようにレイアウト(バイナリ形式):
SEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMM
infinity値は、すべて1の指数とすべて0の仮数で示されます(符号ビットは負の無限大と正の無限大を区別します)。
NaN値は、すべて1の指数とゼロ以外の分数(aquiet NaNには最上位の仮数ビットsetがあり、シグナリングNanにはこのビットがクリアされています)。
したがって、float
を符号なし32ビット整数に「キャスト」することで、これらの表現を明示的にチェックできます(unsigned int
は32ビットタイプです):
int IsInfinite(float test) {
unsigned int mask = *(unsigned int *)(&test);
return ( (mask & 0x7F800000) == 0x7F800000 && (mask & 0x007FFFFF) == 0 );
}
int NotANumber(float test) {
unsigned int mask = *(unsigned int *)(&test);
return ( (mask & 0x7F800000) == 0x7F800000 && (mask & 0x007FFFFF) != 0 );
}
倍精度値の表現も同様ですが、11
指数ビット(62-52)および52
仮数ビット(51-0)。