mql5语言的特点、微妙之处以及技巧 - 页 232

 

解释DBL_EPSILON 的定义:

void OnStart()
  {
   double epsilon = 1.0;
   while(1.0 + epsilon != 1.0)
      epsilon /= 2;
   epsilon *= 2;

   Print(epsilon);  // 2.220446049250313e-16
  }
 
fxsaber # :

这种解释很糟糕,因为

这证明了标准数学性质并不能保证双倍运算。

你提供的例子使用了乘法的 "分配 "性质。
 

另一种解释DBL_EPSILON 含义的方法:

//+------------------------------------------------------------------+
//| Returns the size of a unit in the last place (machine epsilon)   |
//| for a specified double value. This is the positive distance      |
//| between this double value and the representable value next       |
//| larger in magnitude.                                             |
//+------------------------------------------------------------------+
double machine_eps(const double value)
  {
   union _d {double value; long bits;} dbl;
   dbl.value = value;
   dbl.bits++;

   return dbl.value - value;
  }

void  OnStart()
  {
   double epsilon = machine_eps(1.0);

   Print(epsilon);   // 2.220446049250313e-16
  }

DBL_EPSILON 只是[1,2]中连续双倍值之间的间隙大小。

https://www.exploringbinary.com/the-spacing-of-binary-floating-point-numbers/

https://en.wikipedia.org/wiki/Machine_epsilon

 

为了更好地理解DBL_EPSILON,可以考虑递增一个浮点 计数器:

//+------------------------------------------------------------------+
//| Advances a fp double value by a specified number of epsilons.    |
//+------------------------------------------------------------------+
double DoubleAdvance(const double value, const long distance)
  {
   union _d {double value; long bits;} dbl;
   dbl.value = value;
   dbl.bits += distance;

   return dbl.value;
  }

void OnStart()
  {
   double myvalue = 1.0;
   //doubel myvalue = 1024.0;

   // Print the first 10 representable numbers from the counter
   for (int i = 0; i < 10; i++)
     {
      myvalue = DoubleAdvance(myvalue, 1);  // Increment the integer representation by 1 bit
      Print(myvalue);
     }
  }

如果计数器的初始值为 1.0,那么计数器的步长(epsilon)在小数点后第 16 位为 2.220446049250250313e-16 (DBL_EPSILON) ≈ 2。

/*
1.0000000000000002
1.0000000000000004
1.0000000000000007
1.0000000000000009
1.000000000000001
1.0000000000000013
1.0000000000000016
1.0000000000000018
1.000000000000002
1.0000000000000022
*/

如果计数器的初始值为 1024,则计数器 小数点后第 13 位的步长(epsilon )为 2.2737363675443232321e-13 (1024 * DBL_EPSILON) ≈ 2

/*
1024.0000000000002
1024.0000000000005
1024.0000000000007
1024.000000000001
1024.0000000000011
1024.0000000000014
1024.0000000000016
1024.0000000000018
1024.000000000002
1024.0000000000023
*/

如果计数器的初始值是 4503599627370496 (2^52),那么计数器的步长将是 1.0 (2^52 * DBL_EPSILON)= 1。 在这个范围内,双倍计数器的行为与整数计数器类似,不能表示分数。

/*
 4503599627370497.0
 4503599627370498.0
 4503599627370499.0
 4503599627370500.0
 4503599627370501.0
 4503599627370502.0
 4503599627370503.0
 4503599627370504.0
 4503599627370505.0
 4503599627370506.0
*/

我们可以看到,较小的数字之间的间隙较小,而较大的数字之间的间隙较大。

因此,DBL_EPSILON 就是相对误差率。相对是指相对于数字的大小。

在 1.0 时,绝对误差 = 1 * 2.2204460492503131e-016 (DBL_EPSILON)。

d 时,绝对误差 ≈ d * DBL_EPSILON。

(DBL_EPSILON 是 1.0 时的参考利率,类似于银行的年利率,等于 2^-52)。


附带说明:如果您尝试打印 1024.0000000000003,它将打印 1024.0000000000002(四舍五入到最接近的可表示数),因为 1024.0000000000003 不是一个可表示数(不存在 fp 数)。

这就是所谓的表示错误:

void OnStart()
  {
   Print(1024.0000000000003);  // 1024.0000000000002
  }

上一个/下一个可表示数是通过位操作(如前面的枚举:DoubleAdvance(value, -1))或使用 DBL_EPSILON 得到的:

void OnStart()
  {
   double myvalue = 1024.0000000000014;
   Print( myvalue * (1 - DBL_EPSILON) );  // 1024.0000000000011
   Print( myvalue * (1 + DBL_EPSILON) );  // 1024.0000000000016
  }

DBL_EPSILON主要 用于估计(或纠正)对二进制数进行数学运算后的 fp 舍入误差(数值分析):

|true result - fp result| / true result <= DBL_EPSILON

 

在 MT5 测试器中,如果使用的是遗传优化算法不是自定义 优化标准,是否会禁用 OnTester() 调用?

我认为不会。但我希望...最好不要进行配置解析。

PS.CARAUL!一切都没了!每次优化(应该/不应该)都会调用 OnTester(),这会大大增加优化的总时间!

谁能帮帮我...... )))))

 
有高手能回答一下, IP_ADAPTER_INFO 怎么定义吗?这样定义取到的值不对 
struct  IP_ADAPTER_INFO {
  // struct _IP_ADAPTER_INFO *Next;            // 下一网卡信息  
   uint                   ComboIndex;         // 组合索引  
   uchar                   AdapterName[256];   // 网卡名称  
   uchar                   Description[256];   // 网卡描述  
   uchar                  Address[6];         // MAC地址  
   uint                    AddressLength;      // MAC地址长度
   uint                    Index;              // 网卡索引
   uint                    Type;               // 网卡类型
   bool                    DhcpEnabled;        // 是否启用DHCP      
   uchar                    CurrentIpAddress[16];// 当前IP地址
   uchar                    IpAddressList[16];  // IP地址列表
   uchar                    GatewayList[16];    // 默认网关  
   uchar                    DhcpServer[16];     // DHCP服务器
   datetime               LeaseObtained;       // 获得租约时间
   datetime               LeaseExpires;        // 租约过期时间
};

#import "iphlpapi.dll"
    int GetAdaptersInfo(IP_ADAPTER_INFO &AdapterInfo[], int &Size); 
#import
 
稍稍提前当地时间,就会立即断开与交易服务器的连接。
2023.05.24 11:11:15.645 '4999464569': connection to MetaQuotes-Demo lost
 

在搜索过程中,我发现了一个有趣的未记录功能

可以隐藏对话框的输入注释

input int  param=0;  /* показываемый комментарий */   // комментарий для программиста

原帖在此

https://www.mql5.com/ru/forum/1271#comment_9019

Предложение по комментариям к внешним переменным
Предложение по комментариям к внешним переменным
  • 2010.06.30
  • www.mql5.com
Общее обсуждение: Предложение по комментариям к внешним переменным
 
lynxntech #:

在搜索过程中,我发现了一个有趣的未记录功能

您可以隐藏对话框的输入注释

原帖在此

https://www.mql5.com/ru/forum/1271#comment_9019

谢谢,错过了...很有用
 

在 Tester 中,历史记录表仅在两种情况下被覆盖。

  1. HistorySelect 调用。
  2. 调用 OnTrade(即使未指定)。
这样做是为了节省资源。这就是为什么会出现这样的歧义。

#include <MT4Orders.mqh> // https://www.mql5.com/ru/code/16006

#define  Ask SymbolInfoDouble(_Symbol, SYMBOL_ASK)

void OnTick()
{
  const ulong Ticket1 = OrderSend(_Symbol, OP_BUYLIMIT, 1, Ask - 1000 * _Point, 0, 0, 0);
  const ulong Ticket2 = OrderSend(_Symbol, OP_BUYLIMIT, 1, Ask - 1000 * _Point, 0, 0, 0);

  OrderDelete(Ticket2);
  HistorySelect(0, INT_MAX); // Если убрать эту строку, то конечный Print-результат будет иным.
  
  OrderDelete(Ticket1);    
  HistorySelect(0, INT_MAX);
  
  for (int i = 0; i < HistoryOrdersTotal(); i++)
    Print(HistoryOrderGetTicket(i)); // 2 3 или 3 2.
      
  TesterStop();
}
搜索字符串:Uluchshenie 064.