mql5言語の特徴、微妙なニュアンスとテクニック - ページ 146

 
fxsaber:

最初の投稿からクローズドでした。最小の数字に1より小さいものをかけると、0になる。

正しいコードはどのようなものでしょうか?

// Неправильно написанная функция.
double WrongFunc( const double Num )
{
  return(Num ? 1 / (0.1 * Num) : 0);
}
 
Igor Makanu:

正しいコードとはどのようなものでしょうか?

 
fxsaber:
void OnStart()
{
  double d = DBL_MIN - DBL_MIN/10.0;
  Print(WrongFunc(d));
}
//_______________________________________________________________________
double WrongFunc( const double Num )
{
  return(0.1 * Num ? 1 / (0.1 * Num) : 0);
}

コンパイル: 式がブール値でない

結果:Inf



縁起でもない

 
ノープロブレム
bool IsNull( const double Num )
{
  return(MathAbs(Num) < DBL_MIN);
}

double WrongFunc( const double Num )
{
  return(!IsNull(0.1 * Num) ? 1 / (0.1 * Num) : 0);
}


自分ではやらないんです。


美意識の高い人は、適当な演算子でDOUBLE構造を作ればいい。しかし、これらはすべて、実践とはあまり関係がありません。本来の実用例では

トレーディング、自動売買システム、ストラテジーテストのForUM

mql5言語の特徴、複雑な仕組みとテクニック

fxsaber, 2019.10.28 07:24

チェックでもゼロで割り算に 引っかかる方法。
void OnStart()
{  
  const double Profit = 100;
  const double Lots = 1;

  double TickValue[];  
  ArrayResize(TickValue, 1);
  
  const double Points = TickValue[0] ? Profit / (Lots * TickValue[0] * _Point) : 0; // zero divide    
}


このエラーは、事実上、理解できる。しかし、このようなコードを書いていると、ゼロによる除算を避けるためには、このようなチェックだけでは不十分であることが、必ずしも明らかではありません。


作成される配列の項目をゼロにすればよいのです。この場合、衝突の原因となるのは、初期化が行われていないことです。だから、単純にコードでゼロにしたんです。わざわざ一般的な見方をする必要はないだろう。

 
Igor Makanu:

コンパイル:式がブール値でない

結果:Inf



縁起でもない

何かおかしいぞ。

#define  DBL_MIN_DENORM  4.94066 e-324
   Print(DBL_MAX*1.1); // inf
   Print(DBL_MIN_DENORM*0.5); // 0

ゼロで割ると なぜfpu例外が発生するのか、少なくとも私にとってはもっと分かりにくいです。

 
Vict:

何かがあなたを間違った方向に連れていっている。

void OnStart()
{
  double Num=0.0;
  if(0.1 * Num){} // expression not boolean     
}

fxsaber
こちらも問題なし

bool IsNull( const double Num )
{
  return(MathAbs(Num) < DBL_MIN);
}

void OnStart()
{
  union ULongTODouble {
      ulong ul;
      double d;
   } ULongDouble;

   ulong nan = 18446744073708624091;
   ULongDouble.ul = nan;
   double tst = DBL_MIN - DBL_MIN/10000.0;
   Print(tst," --> ",IsNull(tst));
   tst = ULongDouble.d;
   Print(tst," --> ",IsNull(tst));
}
//_______________________________________________________________________

bool IsNull( const double Num )
{
  return(MathAbs(Num) < DBL_MIN || Num!=Num);
}

2019.10.28 20:45:47.010 tst1 (EURUSD,H4) 2.224851351121351e-308 → true

2019.10.28 20:45:47.010 tst1 (EURUSD,H4) -nan --> true

UPDです。

インフを調べる

void OnStart()
{
   double dev = 1.0 / 4.940656458412465 e-324;
   Print("1. dev = ", dev, " ---> ", dev != dev);
   Print("2. dev = ", dev, " ---> ", IsInf(dev));
   dev = 1.0 / dev;

}
//+------------------------------------------------------------------+
bool IsInf(const double Num)
{
   return (Num > DBL_MAX || Num < DBL_MIN);
}
//+------------------------------------------------------------------+

2019.10.28 22:04:00.163 tst1 (EURUSD,H4) 1. dev = inf ---> false

2019.10.28 22:04:00.163 tst1 (EURUSD,H4) 2. dev = inf ---> true


すなわち、予想されるように、それはNaNではない
 
fxsaber:
ここは問題ないです。
bool IsNull( const double Num )
{
  return(MathAbs(Num) < DBL_MIN);
}

C++ double zero divide」でググると、正規化されていない数値では あなたのコードは動作しません。

bool IsZerro(const double value)
{
   return(fabs(value) * DBL_EPSILON == 0.0);
}


瞑想スクリプト )))

void OnStart()
{
   union ULongTODouble {
      ulong ulong_;
      double double_;
   } ULongDouble;
   ulong i = 0;
   ulong count_NaN = 0;
   ulong count_Zerro = 0;
   double last_double = 0.0;
   while(i < ULONG_MAX) {
      ULongDouble.ulong_ = i;
      double double_result = ULongDouble.double_;
      if(IsNaN(double_result)) count_NaN++;
      else {
         if(IsZerro(double_result)) {
            count_Zerro++;
            last_double = double_result;
         }
      }
      if(i % 1000000000 == 0) Print("i = ", i, " , NaN = ", count_NaN, " , Zerro = ", count_Zerro, " , last_double = ", last_double);
      i++;
   }
   Print("NaN = ", count_NaN);
   Print("Zerro = ", count_Zerro);
}
//+------------------------------------------------------------------+
bool IsZerro(const double value)
{
   return(fabs(value) * DBL_EPSILON == 0.0);
}
//+------------------------------------------------------------------+
bool IsNaN(const double value)
{
   return(value != value);
}
//+------------------------------------------------------------------+
bool IsInf(const double value)
{
   return (value > DBL_MAX || value < DBL_MIN);
}
//+------------------------------------------------------------------+
bool IsEqual(const double value1, const double value2)
{
   return(fabs(value1 - value2) <= DBL_EPSILON);
}
//+------------------------------------------------------------------+
 

興味深いテーマですね。ここに 何か発見がありました。特に注目すべきは、理論 ブロックです。

 abs(u - v)/abs(u) <= epsilon
&& abs(u - v)/abs(v) <= epsilon; // (4)
   abs(u - v)/abs(u) <= epsilon
|| abs(u - v)/abs(v) <= epsilon; // (5)

このようにして、すべてのアンダーフローとオーバーフローの 状態を安全に保護することができます。ただし、v またはuが ゼロの場合は、上記は機能しません。このような場合は、例えば(1)の ような別のアルゴリズムで解決することになります。

Floating point comparison - 1.71.0
  • www.boost.org
Unless specified otherwise, when a value of floating-point type is compared inside a assertion, operators , , etc. defined for this type are used. However for floating point type, in most cases what is needed is not an equality (or inequality), but a verification that two numbers are or . For that purpose, a parameter that will instruct the...
 
Igor Makanu:
void OnStart()
{
  double Num=0.0;
  if(0.1 * Num){} // expression not boolean     
}

何に対して?私はバカげた警告しか見ていない、もし絶対に有効であるならば。

ブーリアン変換

整数型、浮動小数点 型、非スコープの列挙型、ポインタ型、ポインタ-メンバ型の prvalue はbool 型の prvalue に変換することができる。

値ゼロ(積分、浮動小数点、非スコープの列挙の場合)、ヌルポインタとヌルポインタからメンバーへの値は偽に なる。その他の値はすべて真と なる。

一般に、これらのIsEqual()、IsInf()、IsZerro()を書くのは全くの無知であると言えます。議論には加わらない。

 
Vict:

何に対して?私はバカげた警告しか見ていないが、もしそれが完全に正しいのであれば。

一般に、IsEqual(), IsInf(), IsZerro() などと書くのは全くの無知である。議論には加わらない。

IsInf()、IsNaN()は動作しています。

IsEqual()とIsZerro()は、「ダブルのトリック」として、いくつかの情報源からググってみると、疑問が残る。

理由: