数字的绝对值

MQL5 API 提供了MathAbs 函数,该函数能够移除数字的减号(如有)。因此,无需手动编写如下冗长的代码:

if(x < 0x = -x;

numeric MathAbs(numeric value) ≡ numeric fabs(numeric value)

该函数返回传递给它的数字的绝对值,即其模数。自变量可以是任何类型的数字。换言之,该函数为 char/ucharshort/ushortint/uintlong/ulongfloatdouble 重载,尽管对于无符号类型,值始终为非负。

在传递字符串时,字符串将被隐式转换为 double 数字,编译器将生成相关警告。

返回值的类型始终与自变量的类型相同,因此,如果类型不同,编译器可能需要将值强制转换为接收变量类型。

函数用法示例在 MathAbs.mq5 文件中提供。

void OnStart()
{
   double x = 123.45;
   double y = -123.45;
   int i = -1;
   
   PRT(MathAbs(x)); // 123.45, number left "as is"
   PRT(MathAbs(y)); // 123.45, minus sign gone 
   PRT(MathAbs(i)); // 1, int is handled naturally
   
   int k = MathAbs(i);  // no warning: type int for parameter and result
   
   // situations with warnings:
   // double to long conversion required
   long j = MathAbs(x); // possible loss of data due to type conversion
   
   // need to be converted from large type (4 bytes) to small type (2 bytes)
   short c = MathAbs(i); // possible loss of data due to type conversion
   ...

务必要注意,将有符号整数转换为无符号整数不等同于取数字的模数:

   uint u_cast = i;
   uint u_abs = MathAbs(i);
   PRT(u_cast);             // 4294967295, 0xFFFFFFFF
   PRT(u_abs);              // 1

同样需要注意的是,数字 0 可以有符号:

   ...
   double n = 0;
   double z = i * n;
   PRT(z);               // -0.0
   PRT(MathAbs(z));      //  0.0
   PRT(z == MathAbs(z)); // true
}

MathAbs 的最佳用法示例之一是测试两个实数是否相等。众所周知,实数的值表示精度有限,在冗长计算过程中,精度可能进一步下降(例如,十个 0.1 的和并不准确得到 1.0)。在大多数情况下,严格条件 value1 == value2 可给出 false,而理论上它们应该相等。

因此,要比较实数值,通常使用以下记数法:

MathAbs(value1 - value2) < EPS

其中 EPS 是一个小的正数值,其指示精度(参见 比较运算 章节中的示例)。