3


2

勾配の計算精度を向上させる方法があるかどうかを知りたいのですが。 (これは数ヶ月前に戻って来ましたhttps://stackoverflow.com/questions/696573/unexpected-loss-of -precision-when-division-doubles/917290#917290 [ここ]

それは変更することによって思われます:

float get_slope(float dXa、float dXb、float dYa、float dYb){return(dXa  -  dXb)/(dYa  -  dYb); }

float get_slope(float dXa、float dXb、float dYa、float dYb){return dXa /(dYa  -  dYb) -  dXb /(dYa  -  dYb); }

改善かもしれません。 提案?

編集:それは精度ではなく、効率です。

3 Answer


5


関数内でそれらを* double *にキャストしてください。

'' '' '

問題に遭遇するのは、明らかに分母がゼロに近い時です。 あなたの勾配は無限大に近づくでしょう。 だから多くはあなたが坂道で何をしたいのかにかかっています。 時々、あなたのデルタyがゼロに近くなるだろうということを知っているなら、あなたは勾配の逆数を計算して代わりにそれを使うことができます。 どれが小さいか - deltaxまたはdeltayの絶対値 - を検出し、勾配または1 /勾配を返すこともできます。 atan2()も調べてください。

'' '' '

入力が10進数で、出力も10進数であることがわかっている場合は、10進数ライブラリを使用してすべての計算を行うことで、浮動小数点数を2進数に変換したり戻したりすることに固有の精度の低下を克服できます。 6502のBCDモードを使用していたので、10進計算にAtari BASICを使用したとき、私がどれほど嬉しかったか覚えています。


1


私はあなたにタイプミスがあると思います。 あなたはおそらく意味

dXa /(dYa  -  dYb) -  dXb /(dYa  -  dYb)を返します。

あなたが与えた最初のフォームはより高い精度を持っていると私は言うでしょう。 dXaとdXbが近いと大きい場合は、減算する前に2つの部門の精度が失われます。


1


余分なサイクルを焼いても構わないのであれば、ループを実行することで精度を上げることができます。

AとBの間の線分の傾きを計算します。

\ {(Xa - (Xa - Xb))、(Ya - (Ya - Yb)}と\ {(Xb(Xa - Xb))、(Yb(Ya - Yb))の間の線分の傾きを計算します。 .. 基本的にAスロープとBスロープ。

次に、得られた斜面を比較します。 差が大きすぎる場合(必要なしきい値を選択)、進み続け、最後にすべての傾斜を平均します。

これは、非常に小さい勾配に対する浮動小数点演算によって引き起こされる異常を滑らかにするのに役立ちます。