Odd floating point math

 
Hi there,

I have noticed some apparent odd MT floating point math which I hope someone can help me explain.

This is a very simple example just to illustrate the odd problem I seem to have found.

Lets take a simple calculation.

Spread = Ask - Bid

If we assume that Ask is 1.0003 and Bid is 1.0000 then Spread should equal 0.0003.

If one subtracts 0.0003 from Spread then the result should be precisly zero.

The following script emulates this equation and outputs its results.

//+------------------------------------------------------------------+
//| funny_math.mq4 |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008, MetaQuotes Software Corp."
#property link "http://www.metaquotes.net"

//+------------------------------------------------------------------+
//| script program start function |
//+------------------------------------------------------------------+
int start() {

double ask, bid, spread, result;
string result_string;

ask = 1.0003; bid = 1.0000;
spread = ask-bid;

result = spread - 0.0003;
if (result == 0.0) result_string = "result=zero"; else if (result > 0.0) result_string = "result>0.0"; else result_string = "result<0.0";

Print("Calc1: ask="+DoubleToStr(ask, 4)+" bid="+DoubleToStr(bid, 4)+" spread="+DoubleToStr(spread,4)+" result="+DoubleToStr(result, 4)+" "+result_string);

result = NormalizeDouble(spread - 0.0003, 4);
if (result == 0.0) result_string = "result=zero"; else if (result > 0.0) result_string = "result>0.0"; else result_string = "result<0.0";

Print("Calc2: ask="+DoubleToStr(ask, 4)+" bid="+DoubleToStr(bid, 4)+" spread="+DoubleToStr(spread,4)+" result="+DoubleToStr(result, 4)+" "+result_string);

return(0);
}

If one runs the above script it produces the following output...

2008.02.15 14:00:32 funny_math GBPUSD,M1: Calc2: ask=1.0003 bid=1.0000 spread=0.0003 result=0.0000 result=zero
2008.02.15 14:00:32 funny_math GBPUSD,M1: Calc1: ask=1.0003 bid=1.0000 spread=0.0003 result=-0.0000 result<0.0

What gives here? If the variable 'spread' is equal to 0.0003 (i.e. 1.0003 - 1.0000) then subtracting 0.0003 from it should give a 'result' of exactly zero but the output of the 'Calc1' line suggests that 'result' is actually -0.0000, a small number that is less than zero.

If I normalize the result of the calculation for 'spread - 0.0003' then the 'result' is indeed precisely zero as shown on the 'Calc2' line.

Why do I need to do this normalization of 'result' ? The 'spread' variable should be precisely 0.0003 since it is the result of the equation 1.0003 - 1.0000, so 0.0003 - 0.0003 should be precisely 0.0000.

I can't figure this out and I am wondering if there are odd floating point calculations like this in my other MT4 code that I should be normalizing in this fashion.

Can anyone shed any light as to why this is occuring?

Regards,

Laurence.
 
"Should be" and "is" sometimes don't match up.

This is old news...

Do search here or on www.mql4.com

Floating point numbers represented in binary are inexact

Use NormalizeDouble() on both sides of equation

or use function CompareDoubles()

The problem is in binary arithmetic, not restricted to MT4


---
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm

Comparing for equality
Floating point math is not exact. Simple values like 0.2 cannot be precisely represented using binary floating point numbers, and the limited precision of floating point numbers means that slight changes in the order of operations can change the result. Different compilers and CPU architectures store temporary results at different precisions, so results will differ depending on the details of your environment. If you do a calculation and then compare the results against some expected value it is highly unlikely that you will get exactly the result you intended.



In other words, if you do a calculation and then do this comparison:

if (result == expectedResult)

then it is unlikely that the comparison will be true. If the comparison is true then it is probably unstable – tiny changes in the input values, compiler, or CPU may change the result and make the comparison be false.
 
Thank you for the clarification, well explained.
Reason: