Tipi Reali (double, float)

I tipi reali (o tipi a virgola mobile) rappresentano i valori con una parte frazionaria. Nel linguaggio MQL5 ci sono due tipi di numeri floating point(_* a virgola mobile) .Il metodo di rappresentazione dei numeri reali nella memoria del computer è definito dallo standard IEEE 754 ed è indipendente dalle piattaforme, sistemi operativi o linguaggi di programmazione.

Tipo

Dimensione in byte

Valore Minimo Positivo

Valore Massimo

Analogo C++

float

4

1.175494351e-38

3.402823466e+38

float

double

8

2.2250738585072014e-308

1.7976931348623158e+308

double

 

double

double tipo di numero reale che occupa 64 bit (1 bit di segno, 11 bit di esponente e 52 bit di mantissa).

float

float tipo di numero reale che occupa 32 bit (1 bit di segno, 11 bit di esponente e 23 bit di mantissa).

vector

Array unidimensionale di numeri di tipo double. La memoria per i dati viene allocata dinamicamente. Le proprietà del vettore possono essere ottenute utilizzando i metodi, con la quale la dimensione del vettore può essere modificata. La voce vector<double> può essere usata nelle funzioni dei template.

vectorf

Array unidimensionale di numeri di tipo float che può essere utilizzato al posto di vector se la perdita di precisione non ha importanza. La voce vector<float> può essere usata nelle funzioni dei template.

vectorc

Array unidimensionale di numeri di tipo complex è pensato per gestire numeri complessi. La voce vector<complex> può essere usata nelle funzioni dei template. Le operazioni sui vettori di tipo vectorc non sono ancora state implementate.

matrix

Matrix è un array bidimensionale di numeri di tipo double. La memoria per gli elementi della matrice è distribuita dinamicamente. Le proprietà della matrice possono essere ottenute utilizzando i metodi, con la quale la forma della matrice può essere cambiata. La voce matrix<double> può essere usata nelle funzioni dei template.

matrixf

Array bidimensionale di numeri di tipo float che può essere utilizzato al posto di matrix se la perdita di precisione non ha importanza. La voce matrix<float> può essere usata nelle funzioni dei template.

matrixc

Array bidimensionale di numeri di tipo complex è pensato per gestire numeri complessi. La voce matrix<complex> può essere usata nelle funzioni dei template. Le operazioni sulle matrici di tipo matrixc non sono ancora state implementate.

 

Il nome double significa che la precisione di questi numeri è due volte l'accuratezza del tipo di numerifloat. Nella maggior parte dei casi, il tipo double è il più conveniente. In molti casi la precisione limitata dei numeri float non è sufficiente. Il motivo per cui il tipo float è ancora usato, è per salvare la memoria (questo è importante per grandi array di numeri reali).

Costanti in floating-point consistono di una parte intera, un punto (.) e la parte frazionaria. Le parti intera e frazionaria sono sequenze di cifre decimali.

Esempi:

   double a=12.111;
   double b=-956.1007;
   float  c =0.0001;
   float  d =16;

C'è un modo scientifico di scrivere costanti reali, spesso questo metodo di registrazione è più compatto di quello tradizionale.

Esempio:

   double c1=1.12123515e-25;
   double c2=0.000000000000000000000000112123515// 24 zero dopo il punto decimale
   
   Print("1. c1 =",DoubleToString(c1,16));
   // Result: 1. c1 = 0.0000000000000000
   
   Print("2. c1 =",DoubleToString(c1,-16));
   // Result: 2. c1 = 1.1212351499999999e-025
 
   Print("3. c2 =",DoubleToString(c2,-16));
   // Result: 3. c2 = 1.1212351499999999e-025

Va ricordato che i numeri reali sono memorizzati nella memoria con una certa precisione limitata nel sistema binario, mentre generalmente viene utilizzata la notazione decimale . Ecco perché molti numeri che sono appunto rappresentati nel sistema decimale possono essere scritti solo come una frazione infinita nel sistema binario.

Per esempio, i numeri 0,3 e 0,7 sono rappresentati nel computer come frazioni infinite, mentre il numero di 0,25 è memorizzato esattamente così, perché rappresenta la potenza di due.

A questo proposito, si raccomanda di non confrontare due numeri reali per l'uguaglianza, in quanto tale confronto non è corretto.

Esempio:

voidOnStart()
  {
//---
   double three=3.0;
   double x,y,z;
   x=1/three;
   y=4/three;
   z=5/three;
   if(x+y==z) 
      Print("1/3 + 4/3 == 5/3");
   else 
      Print("1/3 + 4/3 != 5/3");
// Risultato: 1/3 + 4/3 != 5/3
  }

Se si ha ancora bisogno di confrontare l'uguaglianza di due numeri reali, allora si può fare in due modi diversi. Il primo modo consiste nel confrontare la differenza tra due numeri con qualche piccola quantità che specifica la precisione del confronto.

Esempio:

bool EqualDoubles(double d1,double d2,double epsilon)
  {
   if(epsilon<0) 
      epsilon=-epsilon;
//---
   if(d1-d2>epsilon) 
      return false;
   if(d1-d2<-epsilon) 
      return false;
//---
   return true;
  }
voidOnStart()
  {
   double d_val=0.7;
   float  f_val=0.7;
   if(EqualDoubles(d_val,f_val,0.000000000000001)) 
      Print(d_val," equals ",f_val);
   else 
      Print("Different: d_val = ",DoubleToString(d_val,16),"  f_val = ",DoubleToString(f_val,16));
// Risultato: Different: d_val= 0.7000000000000000   f_val= 0.6999999880790710
  }

Osservato che il valore di epsilon nell'esempio precedente non può essere inferiore alla costante predefinita DBL_EPSILON. Il valore di questa costante è 2.2204460492503131e-016. La corrispondente costante per il tipo float è FLT_EPSILON = 1.192092896e-07. Il significato di questi valori è il seguente: è il valore più basso che soddisfa la condizione 1.0 + DBL_EPSILON! = 1.0 (per numeri di tipo float 1.0 + FLT_EPSILON! = 1.0).

Il secondo modo offre il confronto della differenza normalizzata di due numeri reali con zero. Non ha senso confrontare la differenza di numeri normalizzati con uno zero, perché qualsiasi operazione matematica con i numeri normalizzati da un risultato non-normalizzato.

Esempio:

bool CompareDoubles(double number1,double number2)
  {
   if(NormalizeDouble(number1-number2,8)==0) 
      return(true);
   else 
      return(false);
  }
voidOnStart()
  {
   double d_val=0.3;
   float  f_val=0.3;
   if(CompareDoubles(d_val,f_val)) 
      Print(d_val," equals ",f_val);
   else 
      Print("Different: d_val = ",DoubleToString(d_val,16),"  f_val = ",DoubleToString(f_val,16));
// Result: Different: d_val= 0.3000000000000000   f_val= 0.3000000119209290
  }

Alcune operazioni del co-processore matematico possono provocare il numero reale valido, che non può essere utilizzato in operazioni matematiche e operazioni di confronto, poiché il risultato di operazioni con numeri reali non validi è indefinito. Per esempio, quando si cerca di calcolare l' arcoseno di 2, il risultato è l'infinito negativo.

Esempio:

   double abnormal = MathArcsin(2.0);
   Print("MathArcsin(2.0) =",abnormal);
// Risultato:  MathArcsin(2.0) = -1.#IND

Oltre al meno infinito c'è il più infinito e NaN (not a number). Per determinare che questo numero non è valido, è possibile utilizzare MathIsValidNumber(). Secondo lo standard IEEE, hanno una particolare rappresentazione macchina. Per esempio, più infinito per il tipo double ha la rappresentanza bit di 0x7FF0 0000 0000 0000.

Esempi:

struct str1
  {
   double d;
  };
struct str2
  {
   long l;
  };
 
//--- Start 
   str1 s1;
   str2 s2;
//---
   s1.d=MathArcsin(2.0);        // Ottiene il numero non valido -1.#IND
   s2=s1;
   printf("1.  %f %I64X",s1.d,s2.l);
//---
   s2.l=0xFFFF000000000000;     // numero non valido -1.#QNAN
   s1=s2;
   printf("2.  %f %I64X",s1.d,s2.l);
//---
   s2.l=0x7FF7000000000000;     // il più grande non-numero SNaN
   s1=s2;
   printf("3.   %f %I64X",s1.d,s2.l);
//---
   s2.l=0x7FF8000000000000;     // il più piccolo non-numero QNaN
   s1=s2;
   printf("4.   %f %I64X",s1.d,s2.l);
//---
   s2.l=0x7FFF000000000000;     // il più grande non-numero QNaN
   s1=s2;
   printf("5.   %f %I64X",s1.d,s2.l);
//---
   s2.l=0x7FF0000000000000;     // Infinito positivo 1.#INF ed il più piccolo non numero SNaN
   s1=s2;
   printf("6.   %f %I64X",s1.d,s2.l);
//---
   s2.l=0xFFF0000000000000;     // Infinito negativo -1.#INF
   s1=s2;
   printf("7.  %f %I64X",s1.d,s2.l);
//---
   s2.l=0x8000000000000000;     // Zero negativo -0.0
   s1=s2;
   printf("8.  %f %I64X",s1.d,s2.l);
//---
   s2.l=0x3FE0000000000000;     // 0.5
   s1=s2;
   printf("9.   %f %I64X",s1.d,s2.l);
//---
   s2.l=0x3FF0000000000000;     // 1.0
   s1=s2;
   printf("10.  %f %I64X",s1.d,s2.l);
//---
   s2.l=0x7FEFFFFFFFFFFFFF;     // Il più grande numero normalizzato (MAX_DBL)
   s1=s2;
   printf("11.  %.16e %I64X",s1.d,s2.l);
//---
   s2.l=0x0010000000000000;     // Il più piccolo positivo normalizzato (MIN_DBL)
   s1=s2;
   printf("12.  %.16e %.16I64X",s1.d,s2.l);
//---
   s1.d=0.7;                    // Mostra il numero di 0.7 - frazione senza fine
   s2=s1;
   printf("13.  %.16e %.16I64X",s1.d,s2.l);
/*
1.  -1.#IND00 FFF8000000000000
2.  -1.#QNAN0 FFFF000000000000
3.   1.#SNAN0 7FF7000000000000
4.   1.#QNAN0 7FF8000000000000
5.   1.#QNAN0 7FFF000000000000
6.   1.#INF00 7FF0000000000000
7.  -1.#INF00 FFF0000000000000
8.  -0.000000 8000000000000000
9.   0.500000 3FE0000000000000
10.  1.000000 3FF0000000000000
11.  1.7976931348623157e+308 7FEFFFFFFFFFFFFF
12.  2.2250738585072014e-308 0010000000000000
13.  6.9999999999999996e-001 3FE6666666666666 
*/

Vedi anche

DoubleToString, NormalizeDouble, Costanti dei Tipi Numerici