価格 != 価格 ? - ページ 7

 

WHRoeder: このコードは良い(特に "added "と "default "をチェックして ください)?また、このスレッドを訪問し、ちょうど最後のページに行く人のための簡単な最後の参照として機能するかもしれません(私がしたように)。

#define LT    0
#define GT    1
#define GTE   2
#define LTE   3
#define EQ    4
#define NEQ   5

bool doublecomp(double a,int type,double b){
  // See https://forum.mql4.com/45053/page4
  // 0 compare doesn't need this function
  switch(type){
    case LT: return(b-a>Point/2.);
    case GT: return(a-b>Point/2.);
    case GTE: return(a-b>-Point); // Added
    case LTE: return(b-a>-Point); // Added
    case EQ: return(!(MathAbs(a-b)>Point/2.));
    case NEQ: return(MathAbs(a-b)>Point/2.);
    default: return(-1); // Added - needed to avoid compile error about not all control paths returning a value
  }
}
 

そのコードは正確ではありません。

if( !MathAbs( a - b ) > Point/2) を使って、どのように等しいかどうかを比較することができますか?それは1.4999 == 1.5000と言うことです。

 
SDC: if( !MathAbs( a - b ) > Point/2) が等しいかどうかを比較するためにどのように使用できますか?1.4999 == 1.5000 となります
  1. それはないです。
    if( ! (MathAbs( a     -  b    ) > Point/2) ) be used to compare for equality? That would tell you 1.4999 == 1.5000
    if( ! (MathAbs(1.4999 - 1.5000  > 0.00005  )
    if( ! (0.0001                   > 0.00005  )
    if( ! (true                                )
    if( false                                  ) 1.4999 is NOT equal to 1.5000
  2. そして、私はPMでRoel13に GEQ/LEQは-Point/2でなければならないと指摘していたのですが、彼はその投稿を編集してくれませんでした
  3. そして、以前投稿したように、等質/非等質が重要な場合のみ、そのような無意味なことを気にする必要があります。ローソクの高値より上でオープンしたい場合、(四捨五入の関係で)ちょうど高値で発動する可能性があっても問題ないでしょうか?もしそうでなければ、bid > high[] を使ってください。
 

私が使っているのは

if(NormalizeDouble(price1-price2,Digits)==0)


または、実勢価格ではない倍率の場合は、より高い精度のものを使用します。

if(NormalizeDouble(value1-value2,8)==0)
 
SDC: 私が使っているのは
if(NormalizeDouble(price1-price2,Digits)==0)
一番 最初の 投稿を読めば、それがなぜ良くないのかが分かるはずです。
 

このコードについてRaptorsの投稿

double TestValue = iClose(NULL, 0, 0);
   
if(TestValue != NormalizeDouble(TestValue, Digits) ) //not equal

を使えばいいんですね。

double TestValue = iClose(NULL, 0, 0);

if(NormalizeDouble(TestValue - iClose(NULL,0,0),Digits)==0) // they are considered equal

私はそのメソッドを様々な方法でテストしましたが、期待された、または望ましい結果を返さないシナリオは見つかりませんでした。
 

最終的なコード...ありがとうWHRoeder

#define LT    0
#define GT    1
#define GTE   2
#define LTE   3
#define EQ    4
#define NEQ   5

bool ComparePrice(double a,int type,double b){
  // See https://forum.mql4.com/45053/page4
  // 0 compare doesn't need this function
  switch(type){
    case LT: return(b-a>Point/2.);
    case GT: return(a-b>Point/2.);
    case GTE: return(a-b>-Point/2.);
    case LTE: return(b-a>-Point/2.);
    case EQ: return(!(MathAbs(a-b)>Point/2.));
    case NEQ: return(MathAbs(a-b)>Point/2.);
  }
  return(-1);
}


また、価格以外のdoubleを比較するための2次関数も必要かもしれませんね...。

bool CompareNormal(double a,int type,double b){
  // With thanks https://forum.mql4.com/45053/page4
  // 0 compare doesn't need this function
  switch(type){
    case LT: return(b-a>0.0000000000000000000000000000001);
    case GT: return(a-b>0.0000000000000000000000000000001);
    case LTE: return(b-a>-0.0000000000000000000000000000001);
    case GTE: return(a-b>-0.0000000000000000000000000000001);
    case EQ: return(!(MathAbs(a-b)>0.0000000000000000000000000000001));
    case NEQ: return(MathAbs(a-b)>0.0000000000000000000000000000001);
  }
  return(-1);
}


MQL4 Reference > Language Basics > Data Types > Real Types (double, float)'も参照してください。

0.00...1の書き方を知っている人がいるかもしれません。

 
Roel13: 0.00...1 を指数表現でうまく書く方法を知っている人がいるかもしれません。
// case LT: return(b-a>0.0000000000000000000000000000001);
// case LT: return(b-a>1.0e-30);
実数型(double, float) - MQL4 Documentationを 参照してください。
上記の例のイプシロン値は、定義済みの定数 DBL_EPSILON よりも小さくはできないことに注意してください。この定数の値は 2.2204460492503131e-016 です。
繰り返しになりますが、等号/非等号が 重要な場合を除けば、どれも必要ではありません。例えば、前回の高値より上でオープンする場合、丸め誤魔化して高値でオープンしないようにします。
 

というわけで、「// 0 compare doesn't need thisfunction」に関連している可能性がある、興味深いものを発見しました。

最新版だけのバグかもしれませんが、よくわかりません。0との比較はもはや正しく機能しない。私は、以下のような不親切な方法に頼らざるを得ませんでした。

outcome=(int(outcome*100)/100.0); // 解像度2桁

0の値が実際に0の値として終了することを確認するためです。

WHRoederさん、ありがとうございます。もっと勉強が必要です :)

 

このトピックは、不必要な複雑さに対処しすぎていると思います。

プログラマの生活を可能な限り楽にするようにしましょう。二重比較を必要とするクラスには定義(どうしても必要ならメソッド)を書こう。

// add more floating point zeros if you need a higher precision
#define  isZero(x) (fabs(x) < 0.000000001)
#define  isEqual(x,y) (fabs(x-y) < 0.000000001)

2つのダブルを比較する必要がある場合は、このような条件で使用します。

if (isEqual(myFirstDouble, mySecondDouble))
{
  // first and second doubles are considered equal
  // do something
}

2つの倍数を比較する必要がある場合は、次のような条件で使用します。倍数がゼロ(またはゼロに非常に近い)かどうかを確認したい場合は、次のような条件を使用します。

if (isZero(myDouble))
{
  // myDouble is considered zero
  // do something
}


余談ですが、多くの投稿で除算について書かれています。

カプセル化されていると、ユーティリティメソッドに「アウトソース」されるコードのコストを忘れてしまいがちです。特に、一度ユーティリティクラスのどこかの素敵なユーティリティメソッドに包まれると、インジケータやEAのいたるところでそれを使い始め、それらがどのような計算 ステップを行うのか長い間忘れてしまっています。ストラテジーテスターを 使うとき、私たちは自分のずさんさのために多くの不必要な時間を支払うことになるのです。

経験則。足し算と引き算は、掛け算と割り算よりずっと速い。除算は最も計算時間がかかるので、可能な限り最適化 しましょう。もし分母がこのループのように固定されていたら...

for(int i=0; i < rates_total; i++)
{
    // ...
    double fraction = someNumeratorValue / 100;
    // ...
}

のように分母がfixなら、分母xをその反転値1/xに置き 換える。

for(int i=0; i < rates_total; i++)
{
    // ...
    double fraction = 0.01 * someNumeratorValue; // replace a denominator with it's inverted value, if possible.
    // ...
}

また、除算の結果が常に同じであれば、計算を一度だけ行い、結果を変数に保存しておけば、コード内のあらゆる場所(例えばループ内)で使用することができます。

double tradesPerDay = totalTradesPerYear/365;

for(int i=0; i < rates_total; i++)
{
    // use precomputed tradesPerDay rather than computing the division here.
}

乾杯。

A.T.