double variable with wrong decimal cases

 
Hi,

I'm runnng this code to increase the lotsize in steps:
   double lotsize = 0.01;
   double lotstep = 0.01;

   for(int i=0; i<10; i++)
      {
      lotsize += lotstep;
      Print("i: ", i, ", lotsize: ", lotsize);     
      }

What I get is this result:

2018.01.12 17:15:58.644 test decimal case USDCHFbo,H1: i: 9, lotsize: 0.11
2018.01.12 17:15:58.644 test decimal case USDCHFbo,H1: i: 8, lotsize: 0.09999999999999999
2018.01.12 17:15:58.644 test decimal case USDCHFbo,H1: i: 7, lotsize: 0.09
2018.01.12 17:15:58.644 test decimal case USDCHFbo,H1: i: 6, lotsize: 0.08
2018.01.12 17:15:58.644 test decimal case USDCHFbo,H1: i: 5, lotsize: 0.07000000000000001
2018.01.12 17:15:58.644 test decimal case USDCHFbo,H1: i: 4, lotsize: 0.06
2018.01.12 17:15:58.644 test decimal case USDCHFbo,H1: i: 3, lotsize: 0.05
2018.01.12 17:15:58.644 test decimal case USDCHFbo,H1: i: 2, lotsize: 0.04
2018.01.12 17:15:58.644 test decimal case USDCHFbo,H1: i: 1, lotsize: 0.03
2018.01.12 17:15:58.644 test decimal case USDCHFbo,H1: i: 0, lotsize: 0.02


Why is not the result of the calculation a value with 2 decimal cases?
I'm just adding two numbers with 2 decimal cases each.


Thanks.
Pedro
 
Pedro Taveira: I'm runnng this code to increase the lotsize in steps:

What I get is this result:

2018.01.12 17:15:58.644 test decimal case USDCHFbo,H1: i: 9, lotsize: 0.11
2018.01.12 17:15:58.644 test decimal case USDCHFbo,H1: i: 8, lotsize: 0.09999999999999999
2018.01.12 17:15:58.644 test decimal case USDCHFbo,H1: i: 7, lotsize: 0.09
2018.01.12 17:15:58.644 test decimal case USDCHFbo,H1: i: 6, lotsize: 0.08
2018.01.12 17:15:58.644 test decimal case USDCHFbo,H1: i: 5, lotsize: 0.07000000000000001
2018.01.12 17:15:58.644 test decimal case USDCHFbo,H1: i: 4, lotsize: 0.06
2018.01.12 17:15:58.644 test decimal case USDCHFbo,H1: i: 3, lotsize: 0.05
2018.01.12 17:15:58.644 test decimal case USDCHFbo,H1: i: 2, lotsize: 0.04
2018.01.12 17:15:58.644 test decimal case USDCHFbo,H1: i: 1, lotsize: 0.03
2018.01.12 17:15:58.644 test decimal case USDCHFbo,H1: i: 0, lotsize: 0.02

Why is not the result of the calculation a value with 2 decimal cases?
I'm just adding two numbers with 2 decimal cases each.

Forum on trading, automated trading systems and testing trading strategies

MathRound fails for one particular number

Fernando Carreiro, 2018.01.01 22:08

He means that the value "0.69" cannot be exactly represented given the way a floating point number works (based on binary and not decimal representation) - hence, why the value gets represented as "0.68999999..." (see below).

You can never really "normalize" it and it is the main reason why both @whroeder1 and myself contest the use of the NormalizeDouble() function. It should in the very least be renamed to something like "RoundDigits()" because it is more of a "rounding" function and does not "normalize" in any way or fashion.


https://www.h-schmidt.net/FloatConverter/IEEE754.html

EDIT: Please note that the above images are for examples of representation in the 4-byte "float", and not the 8-byte "double" which offers more precision but still cannot represent the value "0.69" exactly due to the "binary" nature of the format.

EDIT2: For future readers that have difficulty understanding (or accepting) this concept, of decimal values not having an exact representation with a "float" or a "double", here is an article worth reading:

Why 0.1 Does Not Exist In Floating-Point

Many new programmers become aware of binary floating-point after seeing their programs give odd results: “Why does my program print 0.10000000000000001 when I enter 0.1?”; “Why does 0.3 + 0.6 = 0.89999999999999991?”; “Why does 6 * 0.1 not equal 0.6?” Questions like these are asked every day, on online forums like stackoverflow.com.

The answer is that most decimals have infinite representations in binary. Take 0.1 for example. It’s one of the simplest decimals you can think of, and yet it looks so complicated in binary:


Decimal 0.1 In Binary ( To 1369 Places

The bits go on forever; no matter how many of those bits you store in a computer, you will never end up with the binary equivalent of decimal 0.1.

... Read the rest of the article at: http://www.exploringbinary.com/why-0-point-1-does-not-exist-in-floating-point/

 

I guess I'll have to make all my calculations and comparisons with everything as int.
I dont see any other way to solve my particular problem.

Thanks Fernando.

 
Pedro Taveira: I guess I'll have to make all my calculations and comparisons with everything as int. I dont see any other way to solve my particular problem.

That is the way I currently do it:

Forum on trading, automated trading systems and testing trading strategies

NormalizeDouble not "working"

Fernando Carreiro, 2017.09.23 00:41

Just as a side note.

Initially, when I started with MQL, I would manipulate prices as "doubles". Nowadays, especially in the more complex EA's, I manipulate prices as "ints". At the very first opportunity, I convert a price into ticks:

int priceTicks = (int) round( price / tickSize );

From then on, all my calculations and manipulations are done with "ints". Not only is it more memory compact and much faster, but comparisons are much easier to handle.  Doing a "priceA == priceB" for "doubles" is quite problematic, but not for "ints" because it gives exact matches. Not to mention, that in this way prices, stop sizes, etc. are ALWAYS aligned.

Then, just before I have to place or modify an order, I then convert it back:

priceTicks * tickSize
EDIT: I do the same for volume/lots by using the broker's Lot-Step.
 
Fernando Carreiro:

That is the way I currently do it:

That's exactly what I was thinking.

Thanks again!

 

So obviously I'm not the first to break my teeth on double type, decimals & comparison. 

There's no solution, is there ? 

 

I'm supposed to get there a clean : 0 (dot) 5

And there, something higher than a clean 0 (dot) 5

Whatever the speed. Is there a way to perform that ? I've tried using (int), but 0.499999999998 is rounded to 500000000 as 0.499999*7

 
Icham Aidibe:

I'm supposed to get there a clean : 0 (dot) 5

And there, something higher than a clean 0 (dot) 5

Whatever the speed. Is there a way to perform that ? I've tried using (int), but 0.499999999998 is rounded to 500000000 as 0.499999*7


After you round you have to use either DoubleToString, printf, or StringFormat when printing your doubles to log.

 
Icham Aidibe:

I'm supposed to get there a clean : 0 (dot) 5

And there, something higher than a clean 0 (dot) 5

Whatever the speed. Is there a way to perform that ? I've tried using (int), but 0.499999999998 is rounded to 500000000 as 0.499999*7

Floating point has infinite number of decimals, it's your not understanding floating point and that some numbers can't be represented exactly. (like 1/10.)
          Double-precision floating-point format - Wikipedia, the free encyclopedia

See also The == operand. - MQL4 and MetaTrader 4 - MQL4 programming forum

Stop worrying about it and just format it when printing.

 

What about that ?

   int k=1000000000000000000000000000000000000000000000000000000000000000000;
         if(output*k>0.5*k) 
......

It's unaesthetic, but it's expeditive and it works :-/

 
Comments that do not relate to this topic, have been moved to "Which is faster - Floating-Point or Integer arithmetic?".
Reason: