このコードは、浮動小数点数のIEEE754形式の構造を利用しています。構造自体は、比較操作を高速化するために、このような操作用に特別に設計されています。
各単精度IEEE754番号には、次の3つの部分があります(MSBからLSBの順に)。
- 符号ビット
- 指数部(8ビット)
- 仮数の仮数(23ビット)
f1
次の場合よりも大きいf2
:
f1
正でf2
負です
f1
両方ともf2
正ですが、f1
より大きな指数を持っていますf2
f1
両方ともf2
正であり、同じ指数を持ちますが、f1
より大きな仮数を持ちますf2
f1
とf2
が負の場合、前の2つの反対
2の補数表現の場合、両方の浮動小数点数を整数として比較することができます。残念ながら、IEEE 754は負の数を表すために2の補数を使用しません。そのため、このコードは、数値を符号付き整数として比較できるようにするために変換を実行します。
これは、コードの各行が何をするかについての段階的な解説です。
i1 = *(int*)f1; // reading float as integer
i2 = *(int*)f2; // reading float as integer
これは、ほとんどの32ビットシステムsizeof(int) == sizeof(float)
で浮動小数点数を通常の符号付き整数変数に読み込むという事実を利用しています。
t1 = i1 >> 31;
これはの符号ビットを抽出しf1
ます。が負の場合f1
、そのMSBは負になり1
、したがってi1
負になります。31ビット右にシフトすると符号が保持されるため、i1
負の場合はt1
すべてのビットが1
(-1に等しい)に設定されます。が正の場合f1
、その符号ビットはで0
あり、最終的にt1
はに等しくなり0
ます。
i1 = (i1 ^ t1) + (t1 & 0x80000001);
符号ビットが負の場合、1
この行は2の補数表現への変換を実行します。f1
仕組みは次のとおりです。f1
が正の場合、現在および将来t1
は現在および将来であり、最終的には元の値を保持します。が負の場合、すべてのビットがに設定され、RHSの最初の式はのビット反転になり、2番目の式はに等しくなります。この方法はビット反転に変換され、追加されます。ただし、MSBがクリアされるため、これは正の数になります。そのため、数を負に保つために追加されます。0
(i1 ^ t1)
i1
(t1 & 0x80000001)
0
i1
f1
t1
1
i1
0x80000001
i1
1
0x80000000
t2 = i2 >> 31;
i2 = (i2 ^ t2) + (t2 & 0x80000001);
上記と同じように実行しf2
ます。
return i1 > i2;
結果として得られる2つの符号付き整数を比較するだけです。ほとんどのCPUには、ハードウェアで符号付き比較を実行するための専用の命令があります。