MathMod() bug or an undocumented thing?

 

Hi,

I've used MathMod() function a lot on my code for rounding off prices. But I recently found out that if the division remainder is zero (i.e. the number is an integer product of the divisor) the MathMod() doesn't return zero, it returns the divisor instead.

example:

#property show_inputs

extern double divisor = 0.0005 ;
int start()
{
 double price[3] =  {1.25502, 1.25503, 1.25500};
   for(int i=0; i<3; i++)
   {
      double remainder =  MathMod( price[i], divisor);
      Alert("price[",i,"] = ", DoubleToStr( price[i],Digits)," result = ", DoubleToStr( price[i] - MathMod( price[i], divisor),Digits));
   } 
   Alert("*****************************************************");
 return(0);
}

If you run this test script, the result of the third price is suppose to not change (1.25500), at least in my opinion. I've checked on Excel, as expected, it normally returns the remainder zero, unlike mql4.

For an ugly workaround i use the modulus '%' operator with a function to convert price to int and back to double (% only accept int's). Can someone tell me if this is the way it suppose to be with MathMod()?

 
Double precision math problems are common to most programming languages, not just MQL4. See here for tips on how to cope -> https://www.mql5.com/en/articles/1561.
 
gordon:
Double precision math problems are common to most programming languages, not just MQL4. See here for tips on how to cope -> https://www.mql5.com/en/articles/1561.
...specifically, in this case, it's because 1.255 is represented in a double as 1.25499999999999990.
 

Thanks Gordon & jjc.

The author on gordon's link is practically saying if you're using MathMod() ditch it ! Why keep it? Mql5 - still according to the article - changes this calculation. So I took a peek in mql5 book. No warning/explanation there. It has link to fmod, but can't find anything explaining it. This kinda stuff is low-priority to them I guess.

7. Features of function MathMod


In MQL the MathMod (double v1, double v2) function completely corresponds to the function fmod (double v1, double v2) of MSVC6, because of the direct call for the fmod function from C Runtime Library has used.

In some cases the function fmod of MSVC6 (and also MathMod) gives wrong results.

If you are using the function MathMod in your programs, please replace it to the following function:
double MathModCorrect(double a, double b)
{ int tmpres=a/b;
return(a-tmpres*b);

Note that this remark is for MQL4 only, MQL5 calculates this function by its mathematical definition.

His recommended replacement was the same formula described in the Excel Help, btw. Thanks again.

 
cameofx:

The author on gordon's link is practically saying if you're using MathMod() ditch it ! [...]

Going back to the original reason for your code - rounding prices down - I'd personally do it something like this. You can either use a fixed value for <digits>, e.g. 5, or use MarketInfo(Symbol(), MODE_DIGITS):

MathFloor(NormalizeDouble(<price> / divisor, <digits>)) * divisor

 
That's neat, Jjc. I'll try it. Thanks.
 
int start()
  { Alert("test  mathmod");
  
  //  1
   double x=1025;
   double d=5;
   double z= MathMod(x,d);
   Alert (z);
   
  //  2
    x=1.025;
    d=0.005;
   z=MathMod(x,d);
   Alert(z);
  
  // 3
    x=1.025;
    d=0.005;
   double y=NormalizeDouble(x/d,0);
   z= x-y*d;
   Alert(z);
   
     return(0);
  }

try this one.. i prefer the no 3 formula

test mathmod

Reason: