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(const double value, const double min, const double max); // Remap normalized value [0, 1] to a scale [destMin, destMax]. double Denormalize(const double value, const double destMin, const double destMax) // Clamping (limiting) a number to boundaries (range). T      Clamp(T value, T min, T max); // Wrap a value between min (inclusive) and max (exclusive). T      Wrap(const T value, const T min, const 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(const double value); // Returns pow(10, (int)power), uses fast lookup table for powers. double GetPower10(const int power); // Computes the sign of a value as 1, 0, -1 double MathSign(const 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