8

私はここで少し混乱しています. double が不透明 (バイナリ) フィールドとして格納されている場合でも、double の比較は正しく機能しますか? 私が直面している問題は、double には符号 (正または負) の先行ビットが含まれており、それらがバイナリ データとして格納されている場合、正しく比較されるかどうかわからないという事実です。

ここに画像の説明を入力

LevelDB のキー タプル (例: )の一部として double を使用しており、正と負の数値のデータの局所性を維持したいので、比較が正しく機能することを確認したいと考えています。LevelDB は不透明なフィールドのみをキーとして使用しますが、ユーザーは独自のコンパレータを指定できます。ただし、絶対に必要な場合を除き、コンパレータを指定しないようにしたいだけです。

// Three-way comparison function:
//   if a < b: negative result
//   if a > b: positive result
//   else: zero result
inline int Compare(const unsigned char* a, const unsigned char* b) const 
{
    if (*(double*)a < *(double*)b) return -1;
    if (*(double*)a > *(double*)b) return +1;
    return 0;
}
4

3 に答える 3

3

私のコメントを答えにします。

うまくいかないことが 2 つあります。

  1. いずれか (または両方) のパラメーターがNANの場合、比較は常に false を返します。したがって、バイナリ表現が同じであっても、NAN == NAN常に false になります。さらに、比較推移性に違反します。

  2. いずれかのパラメーターが適切にアラインされていない場合 (char ポインターであるため)、アラインされていないメモリ アクセスをサポートしていないマシンで問題が発生する可能性があります。その場合、パフォーマンス ヒットが発生する可能性があります。

したがって、この問題を回避するには、いずれかのパラメーターが であることが判明した場合に呼び出されるトラップ ケースを追加する必要がありますNAN。(の状態はよくわかりませんINF。)

このトラップ ケースが必要なため、独自の比較演算子を定義する必要があります。

于 2011-11-14T05:57:21.687 に答える
1

はい、独自の比較関数を指定する必要があります。これは、double が「ビッグ エンディアン」値として格納されるとは限らないためです。指数は、値がビッグ エンディアン形式で書き出される場合、論理的には仮数の前に表示されますが、仮数の前にメモリ内に常駐しません。

もちろん、同じデータベース内の異なる CPU アーキテクチャ間でデータを共有している場合、データをバイナリ BLOB として保存したという理由だけで、奇妙なエンディアンの問題が発生する可能性があります。

最後に、エンディアンを制御できたとしても、私はそれを信頼しません。たとえば、double が正規化されていない場合、バイナリ データとして比較すると、別の double と正しく比較できない場合があります。

もちろん、比較関数を作成する際には、アラインメントや NAN や INF などの奇数の値について他の人が述べたことすべてに注意を払うことが重要です。しかし、あなたがそれを書くべきかどうかについては、それは本当に良い考えだと言わざるを得ません.

于 2011-11-14T06:26:55.273 に答える
1

あなたの数値形式はIEEE 754標準に準拠していると思います。その場合、単純な符号付き整数の比較は機能しません。両方の数値が負の場合、比較の結果は逆になります。したがって、独自のコンパレータを提供する必要があります。

于 2011-11-14T07:40:57.000 に答える