2

.NET でいくつかの地理座標を処理するメソッドがあり、座標の 1 つに 256 が渡された場合に 0 になるような座標ペアを格納する構造体があります。ただし、ある特定のインスタンスでは、約 255.99999998 が計算され、構造体に格納されます。255.9999998 が出力されてもかまいませんが、デバッガーが 255.99999998 を表示したときに 256 が出力されるという事実は問題です。保存と表示の両方を 0 にするとさらに良いでしょう。

具体的には、比較の問題があります。255.99999998 は 256 に十分近いので、256 と等しくなるはずです。double を比較するときはどうすればよいですか? ある種のイプシロン値を使用しますか?


編集:具体的には、私の問題は、値を取得し、いくつかの計算を実行してから、その数値に対して反対の計算を実行し、元の値を正確に戻す必要があることです。

4

4 に答える 4

3

これは、数値の保存方法ではなく、数値の印刷方法に問題があるように思えます。Adoubleは有効数字が約 15 桁あるため、256 から 255.99999998 を正確に割り出すことができます。

于 2010-06-23T01:37:42.523 に答える
1

イプシロンアプローチを使用することもできますが、イプシロンは通常、浮動小数点演算が不可逆であるという事実を回避するためのファッジです。

バイナリ浮動小数点を完全に回避し、優れたRationalクラスを使用することを検討してください。

上記の計算は、Rationalタイプで得られるようにロスレス演算を実行している場合、おそらく256になる予定でした。

有理数型は、RatioまたはFractionクラスの名前で表すことができ、記述はかなり簡単です。

これが1つのです。ここに別のものがあります


編集....

問題を理解するには、10進値0.01を2進表現に変換するときに、有限メモリに正確に格納できないことを考慮してください。この値の16進表現は0.028F5C28F5Cであり、「28F5C」は無限に繰り返されます。したがって、計算を行う前でも、0.01をバイナリ形式で格納するだけで正確性が失われます。

RationalクラスとDecimalクラスは、パフォーマンスコストはかかりますが、この問題を克服するために使用されます。有理型は、値を表す分子と分母を格納することにより、この問題を回避します。10進型は、2進化10進形式を使用します。これは、除算で不可逆になる可能性がありますが、一般的な10進値を正確に格納できます。

あなたの目的のために、私はまだRationalタイプを提案します。

于 2010-06-23T01:53:39.033 に答える
1

数値を好きなだけ表示できるフォーマット文字列を選択できます。

double が等しいかどうかを比較する通常の方法は、それらを減算し、絶対値が事前定義されたイプシロン (おそらく 0.000001) より小さいかどうかを確認することです。

于 2010-06-23T01:41:41.403 に答える
0

2 つの値が等しくなるしきい値を自分で決定する必要があります。これは、いわゆる固定小数点数(浮動小数点ではなく) を使用することになります。次に、切り上げを手動で実行する必要があります。

サイズが既知の符号なしタイプ(たとえば、uint32またはuint64が利用可能であれば、.NETはわかりません)を使用し、それを256を法とする固定小数点数タイプとして扱います。

例えば。

typedef uint32 fixed;

inline fixed to_fixed(double d)
{
    return (fixed)(fmod(d, 256.) * (double)(1 << 24))
}

inline double to_double(fixed f)
{
    return (double)f / (double)(1 << 24);
}

または、丸め規則 (最も近い、低い方、高い方、奇数、偶数) に合わせてより精巧に作成されたもの。fixed の上位 8 ビットは整数部分を保持し、下位 24 ビットは小数部分を保持します。絶対精度は 2^{-24} です。

このような数値を足したり引いたりすると、自然に 256 で折り返されることに注意してください。掛け算の場合は注意が必要です。

于 2010-06-24T18:44:13.057 に答える