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结构。但这与实践没有什么关系。在原来的实际例子中。

关于交易、自动交易系统和策略测试的论坛

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

更令人困惑的是,为什么除以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


即如预期的inf,它不是NaN。
 
fxsaber:
这里没有任何问题。
bool IsNull( const double Num )
{
  return(MathAbs(Num) < DBL_MIN);
}

在网上搜索 "C++双零除法",你的代码对非正常化的数字 不起作用,你需要这个。

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)

这样,所有的下溢和溢出 情况都可以得到安全保护。然而,当vu 为零时,上述方法将不起作用。在这种情况下,解决方案是采用不同的算法,例如(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     
}

为了什么?我所看到的是一个愚蠢的警告,如果是绝对有效的话。

布尔转换

一个积分、浮点、非范围枚举、指针和指针到成员类型的pr值可以被转换为一个bool 类型的pr值。

值为零(对于积分、浮点 和无范围的枚举),空指针和空指针到成员的值成为假值。所有其他的值都变成了

一般来说,写这些IsEqual()、IsInf()和IsZerro()是纯粹的无知。我将不参与讨论。

 
Vict:

为了什么?我所看到的是一个愚蠢的警告,如果是完全有效的。

一般来说,写这种IsEqual()、IsInf()、IsZerro()是完全无知的。我将不参与讨论。

IsInf()和IsNaN()正在工作。

IsEqual()和IsZerro()是有问题的,从一些资料中搜到的是 "double的技巧"。