MQL4マスターに質問です。ダブルコンペアについてもう一度。 - ページ 5

 

驚きの結末!どんな桁でも、桁の意味を全く「理解」していないのに、なぜそう思うのでしょうか?

 
Integer:

驚きの結末!どんな桁でも、桁の意味を全く「理解」していないのに、なぜそう思うのでしょうか?

言葉狩りを始めていませんか?明らかに人格攻撃になりそうです。:)
私は、このような説明には参加したくありません。というのも、メリットについて話すことがないのなら、なぜ話す必要があるのでしょうか?
 
VBAG:
プロフェッショナルの皆さんの見識に感謝します

Irtron、 あなたのバリアントを選びました。一般的なケースを想定して少し修正し、確認しました。

int ComparePrice(double a, double b, double digit)
{
a -= b;
b=数字。
なら
を返す(1)。
if (a < -b)
を返します(-1)。
を返します(0)。
}
ありがとうございます。
桁に任意の定義済みの値を渡したいことを明確にするのを忘れていました。
double digit14=0.00000000000001;
double digit12=0.000000000001;
double digit8=0.00000001;
double digit4=0.0001;
double digit2=0.01;
で、要求される精度を決定します。
この機能については、非常に高速に動作します。
イルトロン さん、いつもありがとうございます。

 
Irtron:
整数

驚きの結末!桁が何であるかも全く「理解」していないのに、なぜどんな桁でもそう思うのでしょうか?

言葉を選び始めた?明らかに、次は人格攻撃をしてきますね。:)
私は、このような説明には参加したくありません。というのも、メリットについて話すことがないのなら、なぜ話す必要があるのでしょうか?


私はあなたの書いたものを読んだだけです。 あなたの理解は明らかに「あなたのあからさまな...」によって妨げられています。(ようご)

VBAG、ComparePrice()よりも速く2つの数値を比較するNormalizeDouble()という関数があるのに、なぜ車輪を再発明するのですか?

 
Integer:

VBAG、ComparePrice()よりも速く2つの数値を比較するNormalizeDouble()関数があるのに、なぜ車輪を再発明するのでしょうか?

この関数は、2つの倍数を比較し、小数点以下14桁までの <, >, = を返します。 (NormalizeDouble() は8桁までです)
同じような自転車や、より良い代替案があれば、ぜひ利用させていただきたいと思います。
謹んで申し上げます。
ウラジミール
 
VBAG:
整数

VBAG、ComparePrice()よりも速く2つの数値を比較するNormalizeDouble()関数があるのに、なぜ車輪を再発明するのでしょうか?

この関数は、2つの倍数を比較し、小数点以下14桁までの <, >, = を返します(NormalizeDouble()は小数点以下8桁までです)。
もし、似たようなホイールやもっと良い代替品があれば、それを使ってみたいと思います。
謹んで申し上げます。
ウラジミール
ここで興味本位でテストしてみました。
int start()
  {
//----
    double a = 1.23450001, b = 1.23449999;
 
    int start1 = GetTickCount(), c1;
    for ( c1 = 0; c1 < 100000000; c1 ++ ) CD( a, b,0.00000001);
    int end1 = GetTickCount();
    
 
    int start2 = GetTickCount(), c2;
    for ( c2 = 0; c2 < 100000000; c2 ++ )   xNormalize(a,b,8);
    int end2 = GetTickCount();
 
    Print( "CD: ", (end1-start1), ", xNormalize: ", (end2-start2) );
 
    return(0);
   }
 
//+ CompareDouble ---------------------------------------------------+ CompareDouble
int CD(double a, double b, double digit)
{
    a -= b;
    b = digit;
    if (a > b)
        return (1);
    if (a < -b)
        return (-1);
    return (0);
}
 
// Две операции NormalizeDouble----
bool xNormalize(double a, double b,int digit)
  {
   double d1 = NormalizeDouble(a,digit);
   double d2 = NormalizeDouble(b,digit);
   
//   bool bCompare=d2-d1 > 0.0;
   bool bCompare= 0;
   return(bCompare);
2007.09.12 07:15:09 $CheckCompareDouble USDJPY,M5: CD: 20485, xNormalize: 51265

結論
CD関数は、2つの数値を比較し、小数点以下14桁で<、>、=の答えを出す関数で、単にNormalizeDouble()を実行するよりも2倍速く動作します(比較するロジックがない場合でも)。
 
はい、NormalizeDouble()を2回呼ぶとCDより時間がかかり、1回呼ぶと速くなります。14桁の精度は嬉しい限りです :-)
 
私も最近、実数で比較するようにしています

多くの人が、比較には組み込み関数のNormalizeDouble()を使わなければならない、と書いています。(これは開発者も推奨していることです)。
そこで、まず定義したいことがあります。「NormalizeDouble()とは何か、つまり、どのように動作し、どのようなアルゴリズムなのか。

MQL4リファレンス - データ変換 - NormalizeDouble

浮動小数点数を指定された精度に丸める。
...

MQL4で丸めがどのように構成されているかは知りませんが(開発者に聞いてください)、標準的な方法として 浮動小数点数を指定した精度に丸めるというものがあります。
ここで、ある機能。

double MyNormalizeDouble(double value, int digits)
{
    int factor = MathRound( MathPow(10, digits) ); // factor - это множитель,
                                                      с помощью которого мы из VALUE сделаем целое число
    double result = MathRound(factor * value) / factor;
    
    return(result);
}
この関数から、まず実数から整数へ、そして再び実数へ戻ることがわかる。
比較のためには、整数値のみで十分です。

したがって、実数を比較するには、整数に変換するのが最も速く、確実な方法だと思うのです。
比較するとこんな感じになります。

double a;
double b;
int factor = MathRound( MathPow(10, digits) ); // digits - это точность с которой будем сравнивать
                                                           Если сравниваем цены, то это предопределенная переменная Digits
...

if (MathRound( (а - b) * factor )  !=  0)
{
    ... // a != b
}

if (MathRound( (а - b) * factor )  ==  0)
{
    ... // a == b
}

if (MathRound( (а - b) * factor )  >  0)
{
    ... // a > b
}

if (MathRound( (а - b) * factor )  <  0)
{
    ... // a < b
}

これをすべて関数に整形して使うことができる。書くのが面倒くさい!関数の作り方が明確になっているようです。
この方法は、NormalizeDouble()を呼び出すよりも高速だと思います。

MathRound()関数はデフォルトでdoubleを返すので、安全のために整数を返すようにしてもよいでしょう。
最も簡単な方法は、この方法です

int MyMathRound(double value)
{
    int result = MathRound(value);
    return(result);
}
そうすると、比較されるのは整数だけとなり、しかもうまく比較されます。


この方法が一番正しいと思うのですが、いかがでしょうか?
 
gravity001:

だから、実数を整数に変換するのが一番手っ取り早くて確実だと思うんです
比較するとこのようになります。

double a;
double b;
int factor = MathRound( MathPow(10, digits) ); // digits - это точность с которой будем сравнивать
                                                           Если сравниваем цены, то это предопределенная переменная Digits
...

if (MathRound( (а - b) * factor )  !=  0)
{
    ... // a != b
}

if (MathRound( (а - b) * factor )  ==  0)
{
    ... // a == b
}

if (MathRound( (а - b) * factor )  >  0)
{
    ... // a > b
}

if (MathRound( (а - b) * factor )  <  0)
{
    ... // a < b
}

それが正しいやり方だと思うのですが、いかがでしょう?

そんなことはないだろう。ご自身で判断してください。
イルトロンの コードの良さは、そのコンパクトさにあります(余計なものは一切なく、変数まで保存されているのです!)。
そして、少なくとも
(а - b)
の操作ごとに2つの操作を追加すべきだと提案していますね。
(MathRound( (а - b) * factor ) 
それが、スピードのアドバンテージです
 
VBAG:
そんなことはないだろう。自分で判断してください

はい、少し遅くなりました。
int start()
{
    double a, b;
    int start1, start2, end, c;
    
    a = 1.23450001;
    b = 1.23449999;
    
    start1 = GetTickCount();
    
    for (c = 100000000; c > 0; c--)
        ComparePrice(a, b,0.0001);
    
    start2 = GetTickCount();
    
    for (c = 100000000; c > 0; c--)
        intCompare(a, b,10000);
    
    end = GetTickCount();
 
    Print("ComparePrice: ", start2 - start1, ", intCompare: ", end - start2);
 
    return(0);
}
 
int ComparePrice(double a, double b, double point)
{
    a -= b;
    b = point / 2.;
    if (a > b)
        return (1);
    if (a < -b)
        return (-1);
    return (0);
}
 
int intCompare(double a, double b, int factor)
{
    return(MathRound( (a-b) * factor ));
}
ComparePrice:32032、intCompare:35296