Expert Advisors • Indicators • Scripts • Libraries

MQL.RobotFX.org is the biggest collection of MetaTrader expert advisors (MT5 & MT4), indicators, scripts and libraries that can be used to improve trading results, minimize risks or simply automate trading tasks

MetaTrader 4 Libraries | Math Utils (MT4)

MetaTrader Experts, Indicators, Scripts and Libraries

Handy functions for comparison of doubles

int  Compare(double a, double b, int digits);    bool EQ(double a, double b, int digits = 8);  bool NE(double a, double b, int digits = 8);  bool GT(double a, double b, int digits = 8);  bool LT(double a, double b, int digits = 8);  bool GTE(double a, double b, int digits = 8);  bool LTE(double a, double b, int digits = 8);    bool AlmostEqual(double a, double b);  bool EqualDoubles(double a, double b, int significantDigits = 15);  bool IsClose(double a, double b, int maxDifferentSignificantDigits = 2);    int  GetEqualDigits(double a, double b);  int  GetEqualSigDigits(double a, double b);  

Handy functions for rounding of doubles

double Ceil(const double v);  double Ceil(const double value, const int digits);  double Ceil(const double value, const double step);    double Floor(const double v);  double Floor(const double value, const int digits);  double Floor(const double value, const double step);    double Round(const double v);  double Round(const double value, const int digits);  double Round(const double value, const double step);    double Trunc(const double v);  double Trunc(const double value, const int digits);  double Trunc(const double value, const double step);    double RoundToSignificantDigits(const double value, int digits);  double RoundPrice(double pPrice, string pSymbol = NULL);  double RoundVolume(double pVolume, string pSymbol = NULL);    double StripError(const double value);  


Miscellaneous handy functions for doubles

// Determines whether the passed value is an integer.  bool   IsInteger(double value);    // Checks if a number has a specified number of fractional digits.  bool   IsRound(double value, int digits);    // Checks if a number is a whole multiple of some increment.  bool   IsRound(double value, double step);    // Get the decimal part of x (always has the same sign as x)  double Frac(double value);    // Get number of fractional digits after the decimal point.  int    GetDigits(double value);    // Get number of integer digits to the left of decimal point.  int    GetIntegerDigits(double value);    // Get number of significant digits, excluding leading and trailing zeros.  int    GetSignificantDigits(double value);    // Convert value in range [min, max] to y in another range [destMin, destMax].  double Remap(double value, double min, double max, double destMin, double destMax)    // Remap value on a scale [min, max] to normalized scale [0, 1].  double Normalize(double value, double min, double max);    // Remap normalized value [0, 1] to a scale [destMin, destMax].  double Denormalize(double value, double destMin, double destMax)    // Clamping (limiting) a number to boundaries (range).  T      Clamp(T value, T min, T max);    // Clamping (limiting) a number to a maximum value.  T      ClampTop(T value, T max);    // Clamping (limiting) a number to a minimum value.  T      ClampBot(T value, T min);    // Wrap a value into range between [min, max].  T      Wrap(T value, T min, T max);    // Avoids zero divide error that forces the mql program to stop.  double safeDiv(double a, double b);    // Returns the exponent of the scientific notation of a number.  int    FloorLog10(double value);    // Returns pow(10, (int)power), uses fast lookup table for powers.  double GetPower10(int power);    // Computes the sign of a value as 1, 0, -1  double MathSign(double value);  

Handy functions for low-level binary operations on doubles

// Returns the bit representation corresponding to a double value .  long   DoubleToLongBits(double value);    // Returns the double value corresponding to a bit representation.  double LongBitsToDouble(long bits);    // Returns the raw encoding of exponent in the bit representation.  int    RawExponent(double value);    // Returns raw encoding of significand in the bit representation.  long   RawSignificand(double value);    // Returns the unbiased (adjusted) exponent of a double value.  int    GetExponent(double value);    // Returns the significand of a double value.  long   GetSignificand(double value);    // Determine whether number is exactly representable in double.  bool   IsExactDouble(double value);    // Returns the next representable value after x away from zero.  double NextAfter(double value);    // Advances a floating-point number by a specified number of ULPs.  double DoubleAdvance(double value, long distance);    // Returns the size of an ulp of the argument.  double Ulp(double value);    // Returns the difference between two floats expressed in ulp units.  long   UlpDiff(double value1, double value2);  

Handy functions for formatting of doubles to string

// Converting numeric value into the raw hexadecimal text string.  string DoubleToHexadecimal(double value);    // Converting numeric value into the hex float constant string.  string DoubleToHexFloatConstant(double value);    // Converting numeric value into the exact decimal text string.  string DoubleToStringExact(double value);    // Converting numeric value into a string in scientific notation.  string DoubleToExponential(const double value, int digits = -1);    // Converting numeric value into the shortest round-trip string representation.  string Repr(double value);  string Repr(float value);    // Formats double with thousands separator and specified decimals.  string FormatDouble(const double number, const int digits, const string separator=",");  

Exact comparison of doubles

Sometimes, when comparing two double numbers that assumed to be equal, but reached to via different calculations, the comparison goes wrong. Actually A can differ from B by in very little amount (at the 16th decimal place) due to binary rounding errors, so exact comparisons (==!=>>=<<= operators) fail.

Real situations of where exact comparison of doubles can fail

  • Comparing doubles reached via different calculations:

    if (0.1+0.2 == 0.3)  // false  
  • Experts with trailing stop function:

    if (new_sl > OrderStopLoss())  if (new_sl < OrderStopLoss())
  • Experts with hidden take profit function:

    if (Bid >= HiddenTakeProfit)  if (Ask <= HiddenTakeProfit)
  • Comparing price levels in a grid strategy:

    if (Ask < virtual_stopLoss)  if (Bid > virtual_stopLoss)

Loose Comparison

To avoid unexpected results, it is better to replace exact comparisons (==!=>>=<<=), with loose comparisons to overcome the floating-point imprecision. This small library provides the required functions.

//--- exact comparisons can fail  if (Ask < virtual_stopLoss)  if (Bid > virtual_stopLoss)  if (0.1+0.2 == 0.3)  // false    //--- using library functions, results become as expected  if (LT(Ask, virtual_stopLoss))  if (GT(Bid, virtual_stopLoss))  if (EQ(0.1+0.2, 0.3))  // true  
25723