floatの誤差許容比較関数Approximately
孫引きなんですけど、デフォルトのApproximatelyはこうなってるみたいです。
public static bool Approximately(float a, float b)
{
return (double) Mathf.Abs(b - a) < (double) Mathf.Max(1E-06f * Mathf.Max(Mathf.Abs(a), Mathf.Abs(b)), Mathf.Epsilon * 8f);
}
代入を入れて見やすくしたのがこちら
public static bool Approximately(float a, float b)
{
// max(a,b)* 0.000001f まで誤差を許容する。でも両方0に近いと、許容誤差がほぼ0になる
float c1 = 1E-06f * Mathf.Max(Mathf.Abs(a), Mathf.Abs(b));
// a b が0に近いとき用の、許容誤差の最小値(これ以上は小さくならないようにする)
float c0 = Mathf.Epsilon * 8f;
return (double)Mathf.Abs(b - a) < (double)Mathf.Max(c0,c1);
}
自分で定義したほうがいいかも?
理由1 比較値*0.000001f は小さすぎる?
自分で値を操作できたほうがいいかなって
理由2 もっと最適化できる?
許容誤差をaとbの大きいほうを基準に計算していますが、どちらでもいいと思います。
aとbが近い場合、厳密な値の比較が必要ですが、許容誤差もどちらを使ってもほとんど同じです。
aとbが遠い場合、許容誤差の誤差なんて気にならないくらい差があります。
許容誤差係数が0.01のとき、|a|<|b|, |a|=|b|rとして計算してみると、rが0.99から0.990099の間に、aかbどちらを基準にするかで結果が分かれる区間があります。
つまり片方の値の0.99倍の値と比較した場合と、0.990099倍の
100と99.0099を比較したときどうなるか
チェックする差は0.9901
99.0099が基準なら許容誤差は0.990099 許容誤差外にあります。
100が基準なら許容誤差は1 許容誤差内にあります。
コード例
public static bool Approximately(float a,float b)
{
// a * 0.01f までの誤差を認める
// a b どちらでも良い
// 差がある場合は結局false
// 差がない場合は同じくらいの許容誤差(適正)で判断される
float abs_a = Mathf.Abs(a);
int z = Convert.ToInt32(abs_a < 1);
return Mathf.Abs(a - b) < (abs_a + z) * 0.01f;
}