0

Vector3 オブジェクトを正規化する 2 つの方法。Vector3.Normalize() を呼び出し、もう一方はゼロから正規化します。

class Tester {
    static Vector3 NormalizeVector(Vector3 v)
    {
        float l = v.Length();
        return new Vector3(v.X / l, v.Y / l, v.Z / l);
    }

    public static void Main(string[] args)
    {
        Vector3 v = new Vector3(0.0f, 0.0f, 7.0f);
        Vector3 v2 = NormalizeVector(v);
        Debug.WriteLine(v2.ToString());
        v.Normalize();
        Debug.WriteLine(v.ToString());
    }
}

上記のコードはこれを生成します:

X: 0
Y: 0
Z: 1

X: 0
Y: 0
Z: 0.9999999

なんで?

(ボーナスポイント: Why Me?)

4

5 に答える 5

2

彼らがそれをどのように実装したかを見てください(たとえば、asmで)。

たぶん、彼らはもっと速くしたいと思って、次のようなものを作りました:

 l = 1 / v.length();
 return new Vector3(v.X * l, v.Y * l, v.Z * l);

3つの乗算に対して2つの除算を取引する(彼らは、multがdivよりも速いと考えていたためです(これは、現代のfpuではほとんどの場合無効です))。これにより、1 レベル多くの操作が導入されたため、精度が低下しました。

これは、よく引用される「時期尚早の最適化」です。

于 2008-11-27T08:54:53.733 に答える
0

浮動小数点数の丸めエラーによってコードが壊れている場合は、それを修正する必要があります。これは単なる現実です。

于 2008-11-27T09:01:14.233 に答える
0

これは気にしないでください。フロートを使用すると、常に何らかのエラーが発生します。興味がある場合は、double に変更してみて、これが引き続き発生するかどうかを確認してください。

于 2008-11-27T08:39:11.407 に答える
0

float の文字列フォーマットに関する興味深い議論があります。

参考までに:

数値を表すには 24 ビットが必要です。つまり、float の仮数全体 (23 ビット + 1 暗黙のビット) を使い果たしていることになります。
Single.ToString () は最終的にネイティブ関数によって実装されるため、何が起こっているのかはわかりませんが、最後の桁を使用して仮数全体を丸めていると思います。
この背後にある理由は、バイナリで正確に表現できない数値を取得することが多いため、仮数が長くなる可能性があります。たとえば、0.01 は内部的に 0.00999... として表されます。次のように記述してください。

float f = 0.01f;
Console.WriteLine ("{0:G}", f);
Console.WriteLine ("{0:G}", (double) f);

7 桁目で四捨五入すると、期待通りの "0.01" が返されます。

上記の例では、既に見たように、7 桁しかない数字ではこの問題は発生しません。

明確にするために: 丸めは、数値を文字列に変換するときにのみ行われます: 計算があれば、利用可能なすべてのビットが使用されます。

浮動小数点数は外部で 7 桁 (内部で 9 桁) の精度を持っているため、それを超えると (潜在的な癖を伴う) 丸めが自動的に行われます。
浮動小数点数を 7 桁に減らすと (たとえば、左に 1、右に 6)、文字列変換もうまくいきます。

ボーナスポイントについて:

なぜあなた?このコードは「あなたを吹き飛ばしたい」からです。
(バルカン... ブロー... OK. ラメスト. パント. エバー)

于 2008-11-27T08:49:32.823 に答える
0

浮動小数点数を使用する場合は、これを予期する必要があります。基本的な理由は、コンピューターが 2 進数で処理し、これが 10 進数に正確にマップされないためです。

異なるベース間の問題の直感的な例として、分数 1/3 を考えてみましょう。10 進数 (0.333333 .....) で正確に表すことはできませんが、3 進数 (0.1 など) で表すことはできます。

一般に、これらの問題は、計算コスト (操作するビット数が 2 倍になる) を犠牲にして、double ではあまり明白ではありません。しかし、フロートレベルの精度で人を月に連れて行くのに十分だったという事実を考えると、あなたは本当に取りつかれるべきではありません:-)

これらの問題は一種のコンピューター理論の 101 (プログラミングの 101 とは対照的に - 明らかにそれをはるかに超えています) であり、同様のことが定期的に発生する可能性のある Direct X コードに向かっている場合は、次のことをお勧めします。基本的なコンピューター理論の本を手に取り、すぐに読んでください。

于 2008-11-27T08:50:02.417 に答える