4

NaNIEEE の単精度浮動小数点と倍精度浮動小数点の両方での実装と表現に興味があり、「is NaN」関数のこの実装を見つけました。すなわち:

int isnan(double x)
{
    int32_t hx,lx;

    // Move lower 32 bits of double to lx, higher 32 to hx.
    EXTRACT_WORDS(hx,lx,x);

    // Remove sign bit, since -NaN and NaN are both NaN.
    hx &= 0x7fffffff;

    // Equivalent to hx |= (lx != 0).
    hx |= (u_int32_t)(lx|(-lx))>>31;

    // Difference is negative iff (hx & 0x7ff00000) == 0x7ff00000 and (hx & 0x000fffff) != 0.
    hx = 0x7ff00000 - hx;
    return (int)((u_int32_t)(hx))>>31;
}

の目的を理解していませんでし(lx|(-lx)) >> 31た。頭の中で推論に失敗した後、すべての整数でテストし、それ以外の場合は 0、lx = 0それ以外の場合は 1 になることがわかりました。

私が思いついた唯一の理由は(lx != 0)、C 標準が真の操作に割り当てられる整数値を定義していないために代わりに使用できなかったこと (たとえば、真の場合は 1 であることが保証されていない)、またはおそらく!=負の値よりも遅いことです。 or-and-bit-shift。そうでなければ、私は困惑しています。

参考までに、エラーが発生した場合に備えて、すべての整数を試すために使用したコード。

#include <stdio.h>
#include <stdint.h>
int main(void) {
        int32_t i = 0;
        do {
                if (((uint32_t)(i | (-i)) >> 31) == 0)
                        printf("%d\n", i); // prints only 0
        } while (i++ != 0xFFFFFFFF); // overflows to -max_int and then climb to -1
        return 0;
}
4

1 に答える 1

3

(u_int32_t)(lx|(-lx))>>31は と同等lx==0? 0:1です。

ただし、 ではlx==0? 0:1、分岐操作をオブジェクト コードに課しています。

これにより、いくつかのビット単位の操作と比較してパフォーマンスが低下する可能性があります。

それは、基礎となるハードウェア アーキテクチャと指定されたコンパイラに大きく依存します。

しかし、分岐予測ヒューリスティックによっては、一貫性のないパフォーマンスにつながることは間違いありません。

の実行時間は(u_int32_t)(lx|(-lx))>>31、すべての実行で同一であることが保証されています。

于 2014-09-18T07:12:29.777 に答える