Implicit or explicit decimals

 

Hi,

Looking at the image attached and the code below, can you explain, in detail, why spread1 and spread2 are not 5 decimal numbers ?

int OnInit()
{
   double askPrice1 = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double bidPrice1 = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   
   double spread1 = askPrice1 - bidPrice1;
   
   double askPrice2 = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK), 5);
   double bidPrice2 = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_BID), 5);
   
   double spread2 = askPrice2 - bidPrice2;
   
   double spread3 = NormalizeDouble(askPrice2 - bidPrice2, 5);
   
   Comment("askPrice1 = " + askPrice1 + "\nbidPrice1 = " + bidPrice1 + "\nspread1 = " + spread1 + "\nspread2 = " + spread2 + "\nspread3 = " + spread3);
   
   return(INIT_SUCCEEDED);
}

Thank you for your time !

Files:
spread.jpg  21 kb
 
If you wan to have a nice formatted output of decimal number use DoubleToString().
Documentation on MQL5: Conversion Functions / DoubleToString
Documentation on MQL5: Conversion Functions / DoubleToString
  • www.mql5.com
DoubleToString - Conversion Functions - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
 

Forum on trading, automated trading systems and testing trading strategies

Do I have to NormalizeDouble Everything ?

Fernando Carreiro, 2023.07.05 06:20

As already explained, floating point numbers are represented in binary form, not in decimal form. It is impossible to limit the number of "decimal" digits internally.

All you can do is approximate it, which is what NormaliseDouble already does, but you can never get to an exact decimal place because it is binary, not decimal.

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/

 
Fernando Carreiro #:

Sorry, but those references are complicated.

Why don't you try to explain my code line by line ?

So, questions:

1. Is askprice1 a 5 decimal number ?

2. Is bidprice1 a 5 decimal number ?

3. What about spread1 ?

4. Is askprice2 a 5 decimal number ?

5. Is bidprice2 a 5 decimal number ?

6. What about spread2 ?

 
Carl Schreiber #:
If you wan to have a nice formatted output of decimal number use DoubleToString().
Hmm, I didn't think to "falsify" the value of the variables by formatting with DoubleToString().
 
R0bot #:
Hmm, I didn't think to "falsify" the value of the variables by formatting with DoubleToString().
It is what it is.  Format it or have a random number of decimal places.  Up to you
 
Paul Anscombe #:
It is what it is.  Format it or have a random number of decimal places.  Up to you

I think I have found another solution (as you can also see in the image attached), by using NormalizeDouble() function just for spread variable:

double askPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double bidPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   
double spread = NormalizeDouble(askPrice - bidPrice, 5);
   
Comment("askPrice = " + askPrice + "\nbidPrice = " + bidPrice + "\nspread = " + spread);
Files:
spread2.jpg  16 kb
 
R0bot #:

Sorry, but those references are complicated.

Why don't you try to explain my code line by line ?

So, questions:

1. Is askprice1 a 5 decimal number ?

2. Is bidprice1 a 5 decimal number ?

3. What about spread1 ?

4. Is askprice2 a 5 decimal number ?

5. Is bidprice2 a 5 decimal number ?

6. What about spread2 ?

Answering questions as one — all the "double" numbers are floating point and have no fixed number of decimal digits.

You will have to learn this by following the links and researching how binary floating point numbers work.

If you don't learn this, then you will always be handicapped in your coding.

 
R0bot #:

I think I have found another solution (as you can also see in the image attached), by using NormalizeDouble() function just for spread variable:

This is an illusion that sometimes works: https://www.mql5.com/en/forum/316484

Since time immemorial, many complain about it until they understand how doubles work.
NormalizeDouble() not always rounding
NormalizeDouble() not always rounding
  • 2019.06.25
  • www.mql5.com
The NormalizeDouble function almost always rounds to 4 places, but every once in a while I get (ROC is: 0...
Reason: