Informatik Vorlesung 3

Werbung
Informatik Vorlesung 4



10.11.2004
Gleitkommazahlen (elementare Datentypen float und double)
Typenkonversionen (implizit und explizit)
Elementarer Datentyp bool
Gleitkommazahlen (IEEE 754 Standard)
single precision (float)
32-Bit 1Vorzeichenbit, 8 Bit Exponent, 23 Bit Mantisse
double precision (double) 64-Bit 1Vorzeichenbit, 11 Bit Exponent, 52 Bit Mantisse
float Literale:
double Literale
Kommazahlen gefolgt von f, zB 1.0f, 3.1415f
Kommazahlen, zB 1.0, 3.1415
Komma ist Punkt
Der Datentyp float (single precision IEEE 754 Gleitkommazahlen)
32 Bit
8 Bit Exponent
1 Bit Vorzeichen
23 Bit Mantisse
Vorzeichen:
0 Positiv
1 Negativ
8 Bit Exponent:
Der Exponent wird nicht wie eine ganze Zahl gespeichert, sondern
ganzzahlige Repräsentierung plus Bias (127)
Bsp: 0 wird dargestellt durch 01111111 (127)
Achtung: 11111111 (255 ganze Zahl, bzw. 128 als Exponent)
und 00000000 (0 als ganze Zahl bzw. -127 als Exponent)
sind keine zulässigen Exponenten! Diese Exponenten um
spezielle Zahlen zu kodieren:
1) Null: Vorzeichen Bit 0 oder 1,
Exponent 00000000,
Mantisse 0…0
2) Denormalisierte Zahlen:
Vorzeichen Bit 0 oder 1,
Exponent 00000000
Mantisse != 0…0
3) +- Unendlich
Vorzeichen Bit 0 oder 1,
Exponent 11111111
Mantisse 00000000
4) NAN (Not a Number)
Vorzeichen Bit 0 oder 1,
Exponent 11111111
Mantisse != 0…0
Bsp: Berechnung der N-ten harmonischen Zahl HN
N
1 N
1


Mathematisch äquivalente Repräsentierung
HN 
i 1 i
i 1 N  i  1
1
1
 Euler-Mascheroni Zahl ~0.57721566…
Es gilt:
 H N  ln n    
2n  1
2*n
Programm 1
// Programm: harmonic.C
// Berechnung der N-ten harmonischen Zahl auf zwei Arten.
#include <iostream>
int main()
{
// Eingabe
std::cout << "Welche harmonische Zahl H_N (1 <= N <= "
<< std::numeric_limits<unsigned int>::max()
<< ") ? ";
unsigned int N;
std::cin >> N;
// Berechnung der harmonischen Zahl beginnend bei 1
float sum1 = 0.0f;
for (unsigned int i = 1; i <= N; ++i)
sum1 += 1.0f / i;
// Berechnung der harmonischen Zahl beginnend bei N
float sum2 = 0.0f;
for (unsigned int i = N; i >= 1; --i)
sum2 += 1.0f / i;
// Ausgabe
std::cout << "Vorwaertssumme = " << sum1 << "\n"
<< "Rueckwaertssumme = " << sum2 << std::endl;
return 0;
}
Rückwärtssumme viel genauer als Vorwärtssumme, da bei der Rückwärtssumme
kleinere Terme durch „runden“ verloren gehen, als bei der Vorwärtssumme.
Bsp: Berechnung von 1



1
1 1
1  1
 
  
i  1 i 1 i i 2 i
i 1 i i  1
i 1 i
1 
Benutzen um 1 auf 1/10000 zu approximieren
Programm 2
// Programm: one.C
// Berechnet etwas umstaendlich die Zahl eins.
#include <iostream>
int main()
{
// summiere solange, bis der aktuelle Fehler error
// kleiner wird als max_error
// oo
// -1
// Da \ ------------- = 1 , bricht die Schleife
// / i * (i + 1)
// -// i = 1
//
// nach endlich vielen Iterationen ab.
float sum = 0.0f;
// Partialsumme
float error;
// momentaner Fehler
const float max_error = 0.0001f; // Fehlerschranke
unsigned int i = 1;
do {
sum += 1.0f / (i * (i + 1.0f));
++i;
error = 1.0f - sum;
std::cout << "aktueller Fehler ist " << error
<< std::endl;
} while (error > max_error);
// Ausgabe:
std::cout << "Summe = " << sum << ".\n"
<< "Fehler = " << error << std::endl;
return 0;
}
Programm gibt endlos „aktueller Fehler ist 0.000147283“ aus (Endlosschlaufe).
Typkonversion
Wir hatten gesehen 1.0f / i (Ergebnis ist vom Typ float) wobei i vom Typ unsigned int
war.
Regel:
Bei arithmetischen Ausdrücken, die verschiedene Typen beinhalten wird
auf den allgemeinsten Typ umgewandelt.
Reihenfolge der Allgemeinheit: int  unsigned int  float  double
Achtung:
Bei Typenumwandlung kann Genauigkeit verloren gehen
zB. Int  float : Es muss gerundet werden.
Programm 3
#include <iostream>
#include <limits>
#include <cassert>
Int main()
{
const int max = std::numeric_limits<int>::max();
float i1 = imax;
double i2 = imax;
assert (int(i2) == imax);
std::cout << “i1 – i2 = “ << i1 – i2 << std::endl;
unsigned int u = 2u;
i1 = imax + u;
i2 = imax + u;
std::cout << “i1 – i2 = “ << i1 – i2 << std::endl;
return 0;
}
Programm gibt “i1 – i2 = 1” (float – double) und „i1 – i2 = -1“ (unsigned int – double)
aus.
Runden:
imax (auf unserer Architektur 231-1) Kann nicht verlustfrei als dargestellt
werden.
Nicht einfach die letzten Bits Abschneiden bei Konversion von int nach
float, sondern round to nearest, d.h. Gleitkommazahl mit kleinster
Differenz zur ganzen Zahl wird genommen.
In unserem Beispiel wird imax durch 231 (was in float darstellbar ist)
approximiert.  i1 – i2 = 231 – (231 – 1) == 1
Zweites Beispiel:
imax + 2u ist vom Typ unsigned int und hat den Wert 2 31 + 1
i1 vom float wird durch round to nearest auf 231 abgerundet
i2 vom double enthält immer noch 231 + 1
 i1 – i2 == 231 – (231 + 1) == -1
Bem: Falls nächste float Zahl nicht eindeutig, dann rount to even, d.h.
letztes signifikantes Bit ist 0.
Der elementare Datentyp bool
Datentyp von Wahrheitswerten
Literale: true, false
Operatoren: && (logisches und), || (logisches oder)
Boole’sche Ausdrücke
5 *13 3 >10 14 ||4 1 !=9 2 &&5 3 +12 4 >=10 7 ||4 2 <10 1 +12 1.1f
Prioritäten
Auswertungsbaum gemäss Prioritäten und Assoziativitäten.
Short Circuit Evaluation,
die Auswertung eines Boole’schen Ausdrucks wird Abgebrochen, sobald Ergebnis
feststeht.
5 * 3 > 14 || 1 != 2 …
15 > 14 || 1 != 2 …
 true || 1 != 2 …
 true || 2 < 1 + 1.1f
 true
|| 2 < 1 + 1.1f
|| 2 < 1 + 1.1f
|| 2 < 1 + 1.1f
Herunterladen