2013-06-17 5 views
5

私は数学ライブラリで働いており、doubleとの作業の固有の問題のため、a == bと等しい平等比較をすべてMath.Abs(a - b) <= epsilonとしてコーディングしています。constフィールドでscientific記法を使用するには?

また、デフォルトでは、で、書式設定された文字列を、考えられる最大精度で生成する必要があります。つまり、イプシロン0.001の場合、デフォルトのフォーマットはN3になります。

public static class Math3D 
{ 
    internal const int ROUND = 3; 
    public const double Epsilon = 1e-ROUND; 
} 

...と私はコンパイルエラーを得た:

は喜んで私は次のことをやりました。明らかにこれは許可されていません。

私は、相互依存性の定数をconstとして定義することはできません。明らかに私はEpsilonを読み取り専用フィールドとして定義することができますが、それは何らかの概念的に間違っていると感じます。これをどうやって行うのか分かりませんか?

+0

リテラルエラーとはなんですか? – rae1

+0

あなたは実際には 'Epsilon'のための数学をしていて、0.001の値を作りません。 –

+2

'readonly'フィールドを使用すると何が問題になりますか? – xxbbcc

答えて

10

を使用する必要があります。readonlyをここに入力してください。 constは実際にとなるものにはのように変更する必要があります(πなど)。これは、constreadonlyの微妙な違いが原因です。

主な問題は、そうでなければ、shoot yourself in the foot, badlyことができ、あなたがconstの値を変更した場合、あなたはconst使うすべて依存型クライアントを再コンパイルする必要があるということです。値がの場合はに変更されますので、constを使用しないでください。readonlyを使用してください。だから、

、値ががちょうどconstを使用して、ちょうど言う、ROUNDの面でEpsilonの定義については心配しないで、変更するつもりはありませんである場合:

internal const int ROUND = 3; 
public const double Epsilon = 1e-3; 

あなたが本当にしたい場合あなたが誤って他のを変更せずに1を変更しないことを確認、あなたは、コンストラクタで、小さなチェックを追加することができます。

if (Epsilon != Math.Pow(10, -ROUND)) { 
    throw new YouForgotToChangeBothConstVariablesException(); 
} 

あなたも、条件付きコンパイルを追加することができますデバッグリリースでのみコンパイルされます。

それはstatic readonlyを使用し、変更するつもりの場合:

この制限付き
internal readonly int ROUND = 3; 
public static readonly double Epsilon = Math.Pow(10, -ROUND); 

私はconstsとして両方interdependant定数を定義することができる方法を参照してくださいません。 [...]私はこれを行う方法の明白な方法がないのですか?

いいえ、あなたはROUNDEpsilonの間で行くことMath.PowMath.Logを使って数学のいくつかの種類を行う必要があり、それらはconstとコンパイル時の使用のために許容されません。は、単一の入力値に基づいてこれらの2行のコードを吐き出すための小型コードジェネレータを記述していますが、実際にはその時間を投資する価値について疑問を呈しています。

+0

エラーは 'const'によって引き起こされていません。 – rae1

+0

それはまさにポイントです。両方のconstは決して変更されず、それが私がコードを「言いたい」ものにしたいものです。開発中に値を数回微調整するかもしれませんが、私は何とか両者を連鎖できるかどうか疑問に思っていました。ソリューションがない場合、最終的なコードは2つの独立したconstで出荷されることは明らかです。 – InBetween

+0

@InBetween:あなたは解決しようとしている問題を解決するために 'const'を使いたいという、コンパイル時にある種の計算をすることはできません。 – jason

2

1e-ROUND特に、1eは有効なリテラル整数ではありません。あなたは式が実行時まで知られることはありませんときにconstを使用することはできませんので、

public static readonly double Epsilon = 
    decimal.Parse(
     string.Format("1E-{0}", ROUND), 
     System.Globalization.NumberStyles.Float); 

はまた、 static readonlyに注意してください、のような何かをしなければならないでしょう。 static readonlyは、このシナリオでは constと同様に動作します。

あなたはstring Sを扱ってない場合は、いつでも行うことができます、あなたは、定数を使用しているとして、あなたは常にだけでハードコード3.が見て可能性が

public static readonly double Epsilon = Math.Pow(10, -ROUND); 
+2

...数字を文字列にフォーマットして解析する必要がありますか?私は昔ながらのものを呼びますが、私はそれが巨大な概念的な迂回路であることを発見しました。単純な算術計算を使用して数値を取得します。 –

+0

私はこれがとても良いアドバイスだとは思わない。 'Math.Pow()'を使うと、文字列の解析操作を避けることができます。 – xxbbcc

+0

私はできるだけ読みやすいようにしたいと思っていました。 – rae1

1

は、その後、これまでの値を変更するつもりはありません3以外のものには?だからドライについてはあまり心配する必要はありません。

public static class Math3D 
{ 
    internal const int ROUND = 3; 
    public const double Epsilon = 1e-3; 
} 

あなたは3を変更したい場合があります考えている場合は、constは、あなたとあなたの質問は無意味になっ用ではありません。

1

編集:

これは、あなたの質問に直接答えではありませんが、あなたが書き込み可能なフィールドにRoundEpsilonの変更を検討していますか?書式設定/四捨五入にこれらを使用すると、時々変更する必要があることがほぼ保証されています。constフィールドとreadonlyフィールドはどちらも機能しません。

public static class Math3D 
{ 
    internal static int s_Round; 
    internal static double s_Epsilon; 

    static Math3D() 
    { 
     Round = 3; 
    } 

    public static double Epsilon 
    { 
     get 
     { 
      return (s_Epsilon); 
     } 
    } 

    public static int Round 
    { 
     get 
     { 
      return (s_Round); 
     } 
     set 
     { 
      // TODO validate 
      s_Round = value; 
      s_Epsilon = Math.Pow (10, -s_Round); 
     } 
    } 
} 

これは、将来的に物事を変更するときに壊れない、はっきりと読み取れる解決法です。

+0

+1数学ライブラリでの作業としてOPを使用する場合は、書式設定の動作をカスタマイズすることが理にかなっているので、丸め制限を取得および設定するプロパティを設定することをお勧めします。 –

+0

サンプルをありがとう。私は基本的に似たようなことをやめましたが、消費者がライブラリの精度*を変更してデフォルトの "丸め"をいつもフォーマット文字列でカスタマイズできるようにする理由は実際には分かりませんいずれかの問題。したがって、解決策は2つの 'readonly'フィールドになります。 – InBetween

+0

@InBetween私は精度を即座に変更できるいくつかの3Dモデラーを使用しました。これはいくつかの状況で非常に便利な機能です、そのため私はそれを提案しました。 – xxbbcc

関連する問題