web-dev-qa-db-ja.com

C89で人々がnanとinfをチェックする方法

isnan(), isinf()はC99まで仕様に含まれていませんでしたが、C89でそのような関数を実装する方法はありますか?

if (d * 0 != 0)を使用してdがNaNまたはInfであるかどうかを確認できますが、常に:-Werror=float-equalを叫びたいオプションerror: no == or != on float point valueを使用してプロジェクトをコンパイルします。

では、C89でnanとinfをどのようにチェックするのでしょうか。

7
hukeping

システムが 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)。

1
Adrian Mole