Libraries: Math Utils (MT4)

 

Math Utils (MT4):

Handy functions for comparison and rounding of floating-point numbers (prices, lots and money).

Author: amrali

Math Utils (MT4)
Math Utils (MT4)
  • www.mql5.com
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...
 

Update 19 May 2021

Added functions for debugging 

// Converting numeric value into the exact decimal text string.
string DoubleToStringExact(double value);

// Converting numeric value into the raw hexadecimal text string.
string DoubleToHexadecimal(double value);
 
Update 21 May 2021

Added miscellaneous functions

// Convert x in range [min, max] to y in another range [new_min, new_max]. 
// This can be used to rescale indicator values or graphic objects.
double map_range(double x, double min, double max, double new_min, double new_max);

// Get number of digits after the decimal point.
int GetDigits(double number);
 
Please look at this library, it's great:
 
Mohammad Hossein Sadeghi:
Please look at this library, it's great:

I consider the CDouble written by nicholish a good library.

However, I found that some calculations from CDouble are not correct.

My library has very accurate calculations.

Here is a test script to demonstrate the found issues.

#include <Double.mqh>
#include <math_utils.mqh>  // for RoundToStepDown() and GetDigits()

#define PRINT(A) Print(#A + " = ", (A))
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
{
//--- rounding issues in CDouble library
   double lotstep = 0.01;

   PRINT( CDouble::RoundToStepDown(1.15, lotstep) );   // 1.14  incorrect result!
   PRINT( RoundToStepDown(1.15, lotstep) );            // 1.15  correct (value is already rounded)


//--- operator overloading issues in CDouble library
   double  lot1 = 0.1,
           sum1 = lot1 + 0.2;

   CDouble lot2 = 0.1,
           sum2 = lot2 + 0.2;

   PRINT( lot1 == lot2.AsRawDouble() );   // true
   PRINT( sum1 == sum2.AsRawDouble() );   // false


//--- GetDigits() function issues in CDouble library
   PRINT( CDouble::GetDigits(1.12) );     // 16  incorrect result!
   PRINT( CDouble::GetDigits(90.268) );   // 14  incorrect result!
   PRINT( CDouble::GetDigits(1.0954) );   // 16  incorrect result!
   PRINT( CDouble::GetDigits(1.27481) );  // 16  incorrect result!

   PRINT( GetDigits(1.12) );              // 2
   PRINT( GetDigits(90.268) );            // 3
   PRINT( GetDigits(1.0954) );            // 4
   PRINT( GetDigits(1.27481) );           // 5
  }
 
amrali:

I consider the CDouble written by nicholish a good library.

However, I found that some calculations from CDouble are not correct.

My library has very accurate calculations.

Here is a test script to demonstrate the found issues.

You're right, thanks for sharing.

 
Any solution to get digits of the price when there is only zero after decimal, for example GetDigits to return 2 for 3850.00?
 
Mohammad Hossein Sadeghi:
Any solution to get digits of the price when there is only zero after decimal, for example GetDigits to return 2 for 3850.00?
GetDigits work on numeric values (i.e., 3850), your value 3850.00 is string.

Note that:

 GetDigits(1.1200) == 2;  // not 4

 

Update 27 May 2021

Added functions for debugging

// Returns int diff between two floats expressed in epsilon (ulps).
long UlpDiff(const double num1, const double num2);

// Returns the next representable value after x
double nextafter(double num);

Added miscellaneous functions

bool IsRound(const double number, const int digits);

bool IsRoundToStep(const double number, const double step);

Added 'dotnet_cross_check.mq5' script and 'RoundSharp.dll' written in C#.

 
Update 30 May 2021

Added miscellaneous functions

//Get number of integer digits to the left of decimal point.
int    IntegerDigits(double number);

//map x on a scale [min, max] to normalized scale [0, 1].
double normalize(double x, double min, double max);

Handy functions for the binary representation of doubles

//Returns the double value corresponding to a bit representation.
double LongBitsToDouble(long bits);

//Returns the bit representation corresponding to a double value .
long   DoubleToLongBits(double value);

//Returns the unbiased exponent used in the bit representation.
int    GetExponent(double value);

//Returns the mantissa used in the bit representation.
long   GetMantissa(double value);

//Returns the size of an ulp of the argument.
double Ulp(double value);

Handy functions for the string representation of doubles

// Converting numeric value into the shortest string representation
// that round-trips into the same numeric value.
string Repr(double value);
 

Update 1 June 2021

Added new functions:

// 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    Exponent(double value);

// Returns the significand of a double value.
double Significand(double value);

// Determine whether number is exactly representable in double.
bool   IsExactDouble(double value);

// Formats number with thousands separator.
string FormatNumber(const double number,const string separator=",");