2017-08-23 7 views
0

度からラジアンへの変換がどのように機能するのかよく知っていますが、まだ問題はあります。問題はその正確さです。度からラジアンへの変換が正確でない

System.Mathの三角関数はラジアンを使用していますが、角度を差し込む三角関数が必要でした。そこで、CosSinTanの関数を持つHelperクラスを作成しました。これらの関数は、度をラジアンに変換し、Math関数を呼び出すだけです。私はMath.Tan(45)を使用する場合、たとえば、それは0.999999999989代わりの1を返し

public static class Helper 
{ 
    public static double Sin(double degrees) => Math.Sin(degrees * Math.PI/180.0); 
    public static double Cos(double degrees) => Math.Cos(degrees * Math.PI/180.0); 
    public static double Tan(double degrees) => Math.Tan(degrees * Math.PI/180.0); 
} 

しかし、。私の仲間の友達、あなたに私の質問は、これを完全に正確にする方法です。

ありがとうございます。

編集: 私は、小さな誤りがあり、それらを取り除くことは不可能であることを理解します。私が正確に知りたいのは、必要な金額で値を四捨五入する方法です(それほど多すぎず、少なすぎず)ので、とにかく動作します。

EDIT2:

私はコンストラクタを以下ました私のLineクラスの三角法を必要とする: コンテキストので、ここでそれは、この質問で非常に重要である

public Line(Vector2 beginning, Vector2 end) 
{ 
    this.beginning = beginning; 
    this.end = end; 
    this.direction = 180.0 * Math.Atan(end.Y - beginning.Y/end.X - beginning.X)/Math.PI; 
    this.slope = Helper.Tan(direction); 
    this.length = Helper.DistanceBetweenTwoPoints(beginning, end); 
    this.offset = beginning.X; 
} 

問題はどこのラインで発生しますスロープの値を代入します。線形代数を使ってこの直線上にポイントがあるかどうかを確認する必要があります。

公開:Vector2は、double xdouble yの構造です。それで全部です。

答えて

3

倍精度を使用するときは常に丸め誤差が発生します。それは浮動小数点算術の本質です。ダブルは、およそ16桁の10進数を持つことができます。すべての操作でエラーが発生します。 「トリック」は、このエラーを受け入れ、倍精度浮動小数点数を平等と比較することはありません(あなたが何をしているのか分からない限り)。

http://floating-point-gui.de/を参照してください。

ポイントが2つのポイントまたは同様の問題の間にあるかどうかを判断するには、丸める必要はありませんが、許容差を使用する必要があります。ポイントとラインの最短距離を計算し、 。このスレッショルドの大きさはアプリケーションによって異なりますが、簡単な答えはありません。たとえば、あなたのポイントが0..10の範囲にある場合、1e-7の公差が私にとって合理的です。あなたは一般的な実装をしたい場合は、(例えばdist(begin, end) * 1e-8

  • 非常に短い距離の絶対値を(例えば1e-10
  • ポイントの距離が倍の倍率を

    • の最大値を取る必要がありますしかし、あなたはまだ問題にぶつかることがあります。たとえば、行が(10000000.1,0)から(10000000.2,0)になる場合は、hereを参照してください。これは一般的な話題です。x+/- PI/2に近づくにつれてtan(x)が無限大に近づくので、ポイントが行にある場合は計算にHelper.Tan(direction)を経由して、あなたが得るスロープを使用し

    +0

    私はいつもエラーがあることを知っており、なぜ私も知っています。たぶん私は間違った方法で私の質問をした – huB1erTi2

    +0

    @ huB1erTi2:答えを少し拡張しました。これはあなたが意味することですか? –

    +0

    まあ、私は** total **の精度が必要でしたが、不可能であることを知っています。本当に必要なのは値を丸める便利な方法ですが、それほど多くはありません。 – huB1erTi2

    0

    は方向が+/- PI/2に近づくにつれて悪化得る異なる傾きの誤差の異なる量を生成するために起こっていると+/- PI/2で動作しません。

    ポイントがラインの近くにあるかどうかを確認するには、ラインのベクトルとポイントまでのベクトルの外積を使用します。たとえば、AからBまでの行で、ポイントがPの場合、Cross(B-A,P-A)は、Pがライン上にあるときにゼロになります。線長に関係する誤差を解消するには、線積の2乗で除算し、任意の小さな許容誤差epsilonと比較します。

    // A,B, P are Vector2 
    double cross = (B.x-A.x) * (P.y-A.y) - (B.y-A.y) * (P.x-A.x); 
    cross /= (B.x-A.x) * (B.x-A.x) + (B.y-A.y) * (B.y-A.y); 
    double epsilon = 1.0e-6; // 1 millionths of a unit 
    if (Math.abs(cross) < epsilon) { 
        // point P is on line A,B 
    } 
    

    ところでにMath.PIは、それが常に関係なく、あなたが使用しているもののシステムエラーを紹介しません使用して、無理数の近似値です。 PIは単に数字として書くことはできません。実世界では、すべての測定に誤差があり、PI 7桁3.141592のすべての実用的アプリケーションでは十分な精度以上です。

    関連する問題