Realtypen (double, float)

Realtypen (Fliesspunkttypen) stellen die Werte mit Bruchanteil dar. In der Sprache MQL5 gibt es zwei Typen für Fliesspunktzahlen. Darstellungsart  der Realzahlen im Computerspeicher ist vom Standard IEEE 754 bestimmt und hängt nicht von Plattformen, Operationssystemen und Programmiersprachen ab.

Typ

Größe in Bytes

minimale

positive

Größe

Maximale

Größe

Analog in C++

float

4

1.175494351e-38

3.402823466e+38

float

double

8

2.2250738585072014e-308

1.7976931348623158e+308

double

Name double bedeutet, dass die Genauigkeit dieser Zahlen um das Doppelte die Genaugkeit der Zahlen der Art float übertrifft. In meistens Faellen ist die Art double am bequemsten.  Die begrenzte Genauigkeit der Zahle float ist  oft nicht ausreichend.  Der Grund, warum float noch verwendet wird, - Speicheroekonomie bei der Bewahrung (das ist sehr wichtig für grosse Felder der Realzahlen).

Konstanten mit Fliesspunkt bestehen aus dem ganzzahligen Teil, Punkt (.) und Bruchanteil. Ganzzahliger Teil und Bruchanteil stellen Folgen von Dezimalzahlen dar.

Beispiele:

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

Es gibt ein wissenschaftliches Schreibverfahren der Realkonstanten. Oft ist dieses Schreibverfahren kampakter, als das traditionelle.

Beispiel:

   double c1=1.12123515e-25;
   double c2=0.000000000000000000000000112123515// 24 Nulle nach Rechendezimalpunkt 
   
   Print("1. c1 =",DoubleToString(c1,16));
   // Ergebnis: 1. c1 = 0.0000000000000000
   
   Print("2. c1 =",DoubleToString(c1,-16));
   // Ergebnis: 2. c1 = 1.1212351499999999e-025
 
   Print("3. c2 =",DoubleToString(c2,-16));
   // Ergebnis: 3. c2 = 1.1212351499999999e-025

Man muss im Kopf behalten, dass Realzahlen im Bionaersystem mit begrenzter Genauigkeit gespeichert werden, während das allgemeinguelgige System Dezimalsystem ist. Darum können viele Zahlen, die genau im Dezimalsystem geschrieben werden, können im Dualsystem nur als Infinitesimalbruch geschrieben werden.

ZB. werden die Zahlen 0.3 und 0.7 im Computer als  Infinitesimalbrueche vertreten, während die Zahl 0, 25 wird genau gespeichert, da es die Potenz der zwei ist.

In diesem Zusammenhang  ist es nicht empfehlenswert, zwei Realzahlen miteinander zu vergleichen,  weil dieser Vergleich nicht korrekt ist.

Beispiel:

void OnStart()
  {
//---
   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");
// Ergebnis: 1/3 + 4/3 != 5/3
  }

Wenn es aber notwendog ist, zwei Realzahlen miteinander zu vergleichen, kann es mit zwei Verfahren gemacht werden. Das erste Verfahren besteht im Vergleich des Differenzbetrages der zwei Zahlen mit irgendwelcher kleinen Größe, die die Genauigkeit des Vergleiches festlegt.

Beispiel:

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;
   }
void OnStart()
  {
   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));
// Ergebnis: Different: d_val= 0.7000000000000000   f_val= 0.6999999880790710
  }

Es muss bemerkt werden, dass der Wert von epsilon im angeführten Beispiel nicht kleiner als der der internen Konstante DBL_EPSILON sein kann. Der Wert dieser Konstante ist  2.2204460492503131e-016. Für den Typ float ist die entsprechende Konstante FLT_EPSILON = 1.192092896e-07. Der Sinn dieser Werter besteht darin, dass es der minimale Wert ist, der der Bedingung entspricht  1.0+DBL_EPSILON != 1.0 (für die Zahlen float 1.0+FLT_EPSILON != 1.0).

Das zweite Verfahren setzt den Vergleich normalisierter Differenz von zwei Realzahlen mit dem Nullwert. Es ist sinnlos, Differenz normalisierter Zahlen mit Null zu vergleichen, denn im Ergebnis jeder mathemati schen Operation mit normalisierter Zahlen wird das Ergebnis nicht normalisiert.

Beispiel:

bool CompareDoubles(double number1,double number2)
  {
   if(NormalizeDouble(number1-number2,8)==0
      return(true);
   else 
      return(false);
  }
void OnStart()
  {
   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));
// Ergebnis: Different: d_val= 0.3000000000000000   f_val= 0.3000000119209290
  }

Im Ergebnis einiger Operationen des mathematischen Coprozessors kann eine ungueltige Realzahl entstehen, die nicht in mathematischen Operationen und Vergleichsoperationen verwendet werden kann, denn das Ergebnis der Operationen mit ungueltigen Realzahlen ist nicht bestimmt. ZB beim Versuch arc sin  2 auszurechnen, bekommt man das Ergebnis minus Infinitaet.

Beispiel:

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

Ausser minus Infinitaet gibt es auch plus Infinitaet und NaN (keine Zahl). Um festzustellen, das diese Zahl ungueltg ist, kann man die funktion MathIsValidNumber() benutzen Nach Standard IEEE haben Sie spezielle Maschienendarstellung. ZB plus Infinitaet für den Typ double hat Bitdarstellung 0x7FF0 0000 0000 0000.

Beispiele:

struct str1
  {
   double d;
  };
struct str2
  {
   long l;
  };
 
//--- fangen wir an
   str1 s1;
   str2 s2;
//---
   s1.d=MathArcsin(2.0);        // wir bekommen ungueltige Zahl -1.#IND
   s2=s1;
   printf("1.  %f %I64X",s1.d,s2.l);
//---
   s2.l=0xFFFF000000000000;     // ungueltige Zahl -1.#QNAN
   s1=s2;
   printf("2.  %f %I64X",s1.d,s2.l);
//---
   s2.l=0x7FF7000000000000;     // maximale Nichtzahl SNaN
   s1=s2;
   printf("3.   %f %I64X",s1.d,s2.l);
//---
   s2.l=0x7FF8000000000000;     // minimale Nic QNhtzahlaN
   s1=s2;
   printf("4.   %f %I64X",s1.d,s2.l);
//---
   s2.l=0x7FFF000000000000;     // maximale Nichtzahl QNaN
   s1=s2;
   printf("5.   %f %I64X",s1.d,s2.l);
//---
   s2.l=0x7FF0000000000000;     // plus Infinitum 1.#INF und minimale Nichtzahl SNaN
   s1=s2;
   printf("6.   %f %I64X",s1.d,s2.l);
//---
   s2.l=0xFFF0000000000000;     // minus Infinitum -1.#INF
   s1=s2;
   printf("7.  %f %I64X",s1.d,s2.l);
//---
   s2.l=0x8000000000000000;     // negative Null -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;     // minimale normalisierte Zahl(MAX_DBL)
   s1=s2;
   printf("11.  %.16e %I64X",s1.d,s2.l);
//---
   s2.l=0x0010000000000000;     // minimale positive normalisierte (MIN_DBL)
   s1=s2;
   printf("12.  %.16e %.16I64X",s1.d,s2.l);
//---
   s1.d=0.7;                    // zeigen wir, dass die Zahl 0.7 – Infinitesimalbruch 
   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 
*/

Sehen Sie auch

DoubleToString, NormalizeDouble, Konstanten der numerischen Datentypen