Zahlen MNI
Transcription
Zahlen MNI
6 Zahlen 6.1 Beschränktheit von Rechnerzahlen 6.2 Beispiel: Mittelwert zweier Zahlen 6.3 Nichtnegative Ganzzahlen · · · · Zahlsysteme Zahlwandlung BCD-Zahlen ASCII-Zahlen 6.4 Negative Ganzzahlen · Komplementzahlen · Stellenkomplement · Zahlenkreis 6.5 Festpunktzahlen 6.6 Gleitpunktzahlen · · · · · · · · · Darstellung Rechenfehler Schutzziffern Neutrales Runden ANSI/IEEE Standard 754-1985 Kahans Summenformel Zahlwandlung Relativer Fehler Bestimmung von Basis und Stellenzahl 6.7 Langzahl-Arithmetik Im Alltag kennt man verschiedene Zahlklassen: Natürliche Zahlen, Ganze Zahlen, Rationale Zahlen, Reelle Zahlen, Komplexe Zahlen. Rechner bieten oft nur kleine Ausschnitte der obigen Zahlen an, dies führt manchmal zu überraschenden Ergebnissen. So liefern traditionell C/C++ Compiler ab und zu einen negativen Absolutwert einer Ganzzahl: abs (negative Ganzzahl) < 0. Ein weiteres Beispiel für unerwünschte Nebenwirkungen, die bei Mißachtung der Beschränktheit der Zahlbereiche in Rechnern auftreten können, ist: Am 16. 11. 1989 brach das Michigan Terminal System (MTS) der Universität Newcastle upon Tyne zusammen. Fünf Stunden später kollabierten MTS-Installationen an der Ostküste der USA. Der Grund: Ein Datumsüberlauf. MTS verwaltete das Datum als Tag seit dem 1. März 1900 in einer 16-Bit-Ganzzahlvariablen, der 16. 11. 1989 ist der 32.768-te Tag seit Zählbeginn. // // Programmierung als Rätsel? // #include <iostream> int main () { float a = float (0.1); float b = float (0.1); float c = 0; std::cout << " a = " << a << std::endl; std::cout << " b = " << b << std::endl; std::cout << " a*b = " << a*b << std::endl; c += a*b; c -= a*b; std::cout << std::endl << " c = " << c << std::endl; return 0; }//main /* Ausgabe a = 0.1 b = 0.1 a*b = 0.01 c */ = 4.09782e-010 <== Warum? Berechnung des Mittelwerts in einer Zahlenmenge: Man betrachte folgende Zahlenmenge: e Z = { z / z = m * 10 mit −9999 ≤ m ≤ 9999 und –99 ≤ e ≤ 99 } Die kleinste positive Zahl ist: -99 1 * 10 99 Die größte positive Zahl ist: 9999 * 10 Die normalen arithmetischen Operationen auf Z × Z liefern nicht immer ein Ergebnis in Z; viele Ergebnisse sind nur angenähert darstellbar, viele überhaupt nicht. 99 Beispiel: 1*10 10 ∗ 2*10 ist in Z nicht darstellbar. Man betrachte nun das folgende Problem: Berechnung des genäherten Mittelwerts zweier Zahlen a und b aus Z gemäß mw (a, b) = (a + b) / 2, wobei der Fehler so gering wie möglich sein soll. Gewünschte Eigenschaften von mw: (i) (ii) (iii) (iv) (v) min (a, b) ≤ mw (a, b) ≤ max (a, b) mw (a, b) = mw (b, a) mw (−a, −b) = − mw (a, b) mw (a, b) = 0 <==> a = – b Ein Überlauf darf während der Rechnung nicht auftreten. Annahme: Zwischenergebnisse werden auf Signifikanden mit 4 Dezimalziffern reduziert. Probleme mit der Formel: mw (a, b) = (a + b) / 2 Verletzung von (v): 99 z. B. : a = 9123 * 10 99 b = 8123 * 10 Verletzung von (i): 0 z.B.: a = 5001 * 10 0 b = 5003 * 10 0 (a + b) / 2 = 5000 * 10 < min (a, b) Verletzung von (iv): -99 z.B.: a = 2 * 10 -99 b = −1 * 10 (a + b) / 2 = 0 (Unterlauf!) Andere Formeln zur Berechnung des Mittelwerts haben andere Schwächen, z. B.: mw (a, b) = a / 2 + b / 2 Diese Formel vermeidet sicherlich den Überlauf, der relative Fehler wird aber manchmal recht groß. 0 z. B.: a = 2004 * 10 0 b = −2001 * 10 -1 a / 2 + b / 2 = 20 * 10 statt 15 * 10 -1 Dies ist sogar eine Verletzung der Spezifikation von mw. Auch eine Formel wie mw (a, b) = a + (b − a) / 2 führt zu unbefriedigenden Ergebnissen. Aufgabe: Versuchen Sie eine Routine zu definieren, die den Forderungen (i) – (v) gerecht wird. Nichtnegative Ganzzahlen: Dezimalzahl ≡ nichtleere Folge von Dezimalziffern = anan-1 . . . a1a0 (n ≥ 0) Beispiele: 3456 1236713 Wert einer Zahl: Wert (anan-1 . . . a1a0) = n i ∑ a i ∗ 10 i=0 Beispiel: 2 1 Wert (786) = 7 * 10 + 8 * 10 + 6 Verallgemeinerung: Sei B > 1 eine natürliche Zahl, die Zahlen 0, 1, . . ., B–1 nennt man Ziffern im Zahlsystem mit Basis B. Einer Ziffernfolge anan-1 . . . a0 (n ≥ 0) ordnet man den Zahlwert n i ∑ ai ∗ B i=0 zu. Bemerkung: Charakteristisch für eine Ziffer z im Zahlsystem mit Basis B ist: 0 ≤ z < B. Beispiele für Zahlen: Basis 10 (Dezimalsystem): 2 1 0 261 = 2*10 + 6*10 + 1*10 Basis 2 (Dualsystem): 3 2 1 0 1001 = 1*2 + 0*2 + 0*2 + 1*2 Basis 16 (Sedezimalsystem): 2 1 0 3 14 12 = 3*16 + 14*16 + 12*16 = 100410 Bemerkung: Es ist manchmal üblich, die Basis des benutzten Zahlsystems als tiefgestellte Zahl der Ziffernfolge anzuhängen. Konventionell werden die Sedezimalziffern mit Werten größer als 9 durch Buchstaben dargestellt: 10 11 12 13 14 15 ≡ ≡ ≡ ≡ ≡ ≡ a b c d e f oder oder oder oder oder oder A B C D E F Die übliche Schreibweise der Sedezimalzahl 3 14 12 ist daher: 3ec oder 3EC Bemerkung: In C und C++ benutzt man zur Darstellung von Sedezimalzahlen das Präfix 0x oder 0X, somit lautet obige Zahl 0x3ec oder 0X3EC. (Das x in "0x" erinnert an das x in hexadezimal.) Tabelle kleiner Dualzahlen: 0000 0001 0010 0011 0100 0101 0110 0111 = = = = = = = = 0 1 2 3 4 5 6 7 Rechnen im Dualsystem: Additionstafel: 0 0 1 1 + + + + 0 1 0 1 = 0 = 1 = 1 = 10 Beispiel: 1010111100 + 1110011010 11001010110 1000 1001 1010 1011 1100 1101 1110 1111 = = = = = = = = 8 9 10 11 12 13 14 15 Multiplikationstafel: 0 0 1 1 * * * * 0 1 0 1 = = = = 0 0 0 1 Beispiel: 1010 * 110 0000 1010 1010 111100 Bemerkung: Subtraktionen und Divisionen haben nicht immer ein Ergebnis im Bereich der nichtnegativen Ganzzahlen. Arbeitet man mit Zahlen in verschiedenen Zahlsystemen, dann stellt sich die Aufgabe der Zahlwandlung. Die Ziffern einer Zahl im System mit Basis B gewinnt man durch fortgesetzte Division durch B und Restabspaltung. Zahl n 1 = an*B + . . . + a1*B + a0 n-1 ==> Zahl / B = an*B + . . . + a1 ==> a0 ist die gewünschte Ziffer. Rest a0 Beispiel: Wandlung von 29 in Dualdarstellung 29 / 2 14 / 2 7/2 3/2 1/2 damit = 14 = 7 = 3 = 1 = 0 Rest Rest Rest Rest Rest 1 0 1 1 1 2910 = 111012 Den Wert einer Ziffernfolge gewinnt man mittels des Horner-Schemas n n-1 + . . . + a0 an*B + an-1*B = ((...((an * B + an-1) * B + an-2)...) * B + a1) * B + a0 Beispiel: 210123 = (((2 * 3 + 1) * 3 + 0) * 3 + 1) * 3 + 2 = (21 * 3 + 1) * 3 + 2 = 19410 Bemerkung: Die Wandlungsrechnungen sind systemneutral, sie können sowohl im Ursprungsals auch im Zielsystem durchgeführt werden. Aus technischen Gründen wird in heutigen Digitalrechnern die Information in Form von Bitketten dargestellt; dies bedeutet aber nicht zwangsläufig, daß im Dualsystem gerechnet wird. BCD – Codierung der Dezimalziffern: Ziffer 0 1 2 3 4 5 6 7 8 9 Code 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 Beispiel: 693 = 011010010011 Bemerkungen: (i) BCD steht für Binary Coded Decimal. (ii) BCD-Zahlen zeigen das gleiche Rundungsverhalten wie Alltagsrechnungen, daher sind sie in der Finanzwelt beliebt, z. B. bei der Berechnung des Zinseszins. Beispiele anderer Codierungen von Dezimalziffern: (a) Stibitzcodierung (auch Exzeß-3 Codierung): Ziffer 0 1 2 3 4 5 6 7 8 9 Code 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 (b) ASCII-Codierung: Ziffer 0 1 2 3 4 5 6 7 8 9 Code 48 49 50 51 52 53 54 55 56 57 Sowohl in der Stibitzcodierung als auch in der ASCIICodierung kann man für arithmetische Operationen das Rechenwerk für Dualzahlen nutzen. Beispiel: Addition zweier Zahlen in ASCII-Codierung ohne eine Zahlwandlung durchzuführen, die Addition erfolgt im Zahlsystem mit Basis 256. Addenden Z1: Z2: 3826 2645 Darstellung als Bytefolge: ASCII-Z1: ASCII-Z2: Summe S: Addition des magischen Werts: Subtraktion des Korrekturwerts: 51 56 50 54 50 54 52 53 101 110 102 107 150 150 150 150 252 4 253 1 246 6 0 246 4 7 0 1 Addition des Grundversatzes: 48 48 48 48 Ergebnis: 54 52 55 49 Dezimalzahl: 6471 Negative Ganzzahlen: In der Mathematik führt man die negativen Zahlen ein, damit die Subtraktion immer ausführbar ist. Fordert man die "unbeschränkte" Subtraktion für darstellungsbeschränkte Zahlen, dann ergibt sich in natürlicher Weise der Begriff der Komplementzahl. Beispiel: Zahlen mit genau 4 Dezimalziffern Beispielrechnung: 0000 – 2613 7387 Bemerkung: Die Zahl 7387 nennt man das 10–Komplement der Zahl 2613 in der Zahlenmenge der 4–ziffrigen Dezimalzahlen; der Wert von 7387 ist –2613, denn –2613 = 0 – 2613 = 7387. Verallgemeinerung: Definition: Im Bereich der n-ziffrigen Zahlen im Zahlsystem mit Basis B nennt man zwei Zahlen a und b Komplementzahlen, falls n a + b = B gilt. Man kennt noch einen zweiten Komplementbegriff, das Stellenkomplement. Definition: Im Bereich der n-ziffrigen Zahlen im Zahlsystem mit Basis B nennt man eine Zahl a = an-1an-2 . . . a0 das Stellenkomplement der Zahl b = bn-1bn-2 . . . b0, falls gilt: ai + bi = B – 1 für alle i mit 0 ≤ i < n. Bemerkung: (i) Jede Zahl bis auf 0 hat genau eine Komplementzahl. (ii) Das Stellenkomplement bildet man ziffernweise. (iii) Die Komplementzahl läßt sich über das Stellenkomplement bestimmen, denn: n a + b = (B – 1) + 1 n ==> a = ((B – 1) – b) + 1 Verfahren zur Bildung eines Komplements: 1. Bildung des Stellenkomplements. 2. Addition von 1 zum Stellenkomplement. Beispiel 1: Bildung des Komplements von 3862 im 4-ziffrigen Dezimalsystem: 1. Bildung des Stellenkomplements: 9999 – 3862 6137 2. Addition von 1: 6138 damit Komplement (3862) = 6138 Beispiel 2: Komplementzahlen im Dualsystem Annahme: Zahlbreite = 9 Beispiel einer Dualzahl: Stellenkomplement: Addition von 1: 100100100 011011011 011011011 + 000000001 011011100 damit Komplement (100100100) = 011011100 Bemerkung: Bei der Bildung der Komplementzahl im Dualsystem ist die Addition von 1 die aufwendige Operation. Definition der negativen Ganzzahlen: Sei B > 1 die Basis, sei n > 1 die Ziffernzahl, eine Zahl an-1an-2 ... a1a0 ist negativ, falls an-1 > (B–1) / 2 ist, sonst positiv. Beispiel: B = 2, n = 5 positive Zahlen: negative Zahlen: 00000 . . . 01111 10000 . . . 11111 Zahlwert: Wert positiver Zahlen: n −1 i ∑ ai ∗ B i=0 Wert negativer Zahlen: n −1 n i ∑ ai ∗ B − B i=0 Drei Darstellungsarten für Dualzahlen: Bitfolge ZweierEinerVorzeichen komplement komplement und Betrag 0111 0110 0101 0100 0011 0010 0001 7 6 5 4 3 2 1 7 6 5 4 3 2 1 7 6 5 4 3 2 1 0000 0 0 0 1111 1110 1101 1100 1011 1010 1001 1000 -1 -2 -3 -4 -5 -6 -7 -8 -0 -1 -2 -3 -4 -5 -6 -7 -7 -6 -5 -4 -3 -2 -1 -0 Der Zahlenkreis für Ganzzahlen bei Zweierkomplementdarstellung: Übertragsgrenze 0000 1111 1110 -1 0 0001 -2 1101 0010 1 2 -3 1100 0011 3 -4 4 -5 0100 5 1011 0101 -6 6 -7 1010 1001 -8 1000 7 0110 0111 Überlaufgrenze Der Zahlenkreis für Ganzzahlen bei Einerkomplementdarstellung: 0000 1111 1110 -0 0 0001 -1 1101 0010 1 2 -2 1100 0011 3 -3 4 -4 0100 5 1011 0101 -5 6 -6 1010 1001 -7 1000 7 0110 0111 Bemerkung: Der Zahlenkreis veranschaulicht den engen Zusammenhang zwischen Rechnungen bei Einerkomplement- und Zweierkomplementdarstellung. // // Undefiniertes Verhalten in C++ // #include <iostream> #include <climits> int main () { std::cout << << << << << << << std::cout << << std::cout << << return 0; }//main "Falls ein Zwischenergebnis einer " "Rechnung nicht darstellbar ist, " "liegt undefiniertes Verhalten vor." std::endl << std::endl "Ein Beispiel ist die Berechnung " "des Absolutwertes:" std::endl << std:: endl; "\tabs (" << -INT_MAX << ") = " abs (-INT_MAX) << std::endl; "\tabs (" << -INT_MAX-1 << ") = " abs (-INT_MAX-1) << std::endl; // Programmausgabe: Falls ein Zwischenergebnis einer Rechnung nicht darstellbar ist, liegt undefiniertes Verhalten vor. Ein Beispiel ist die Berechnung des Absolutwertes: abs (−2147483647) = 2147483647 abs (−2147483648) = −2147483648 Positive Festpunktzahlen: Beispiel einer Festpunktzahl im Dualsystem: 101.10112 2 1 0 = 1*2 + 0*2 + 1*2 –1 –2 –3 –4 + 1*2 + 0*2 + 1*2 + 1*2 = 5.687510 Allgemeine Interpretation im B-Zahlsystem: bnbn–1 . . . b1b0 . b–1b–2 . . . b–m = n ∑ bi ∗ B i=0 i + −m −i ∑ b−i ∗ B i = −1 Bemerkungen: (i) Zur Darstellung von Zahlen mit festem Zahlpunkt verwendet man Ganzzahlen; den Zahlpunkt merkt sich anderswo. (ii) Die Verwendung von Festpunktzahlen erfordert für jede Rechnung eine rechnungsspezifische Kenntnis der auftretenden Zwischenwerte, um eine sinnvolle Wahl zwischen Genauigkeit und Größe des Zahlbereichs treffen zu können. (iii) Bei Zahlwandlungen werden der Ganzteil und der Bruchteil einer Zahl getrennt gewandelt. Gleitpunktzahlen: Dezimalbrüche sind oft unübersichtlich, z. B. a = b = 0.000000000000000000000238 2380000000000000000000000 übersichtlicher ist die Exponentenschreibweise: −23 a = 2.38 ∗ 10 +24 b = 2.38 ∗ 10 Bei fester Basis (hier: 10) kann man auf die explizite Angabe der Basis verzichten, eine Gleitpunktzahl läßt sich dann als Paar ganzer Zahlen (Signifikand, Exponent) darstellen. a = ( 23800, −19 ) b = ( 23800, +20 ) Das Kennzeichen von Zahlen auf Rechnern ist ihre beschränkte Ziffernzahl, daher sind die Ergebnisse arithmetischer Operationen oft nur angenähert oder überhaupt nicht darstellbar. Seien a und b Rechner-Gleitpunktzahlen, sei ° eine arithmetische Operation, dann gilt: Berechnetes (a ° b) = (a ° b) ∗ (1 + err), wobei err eine kleine Zahl ist, deren Absolutbetrag sich aus den benutzten Algorithmen abschätzen läßt. Für die folgenden Beispiele mögen die Annahmen gelten: Signifikandendarstellung: Vorzeichen, 5 Dezimalziffern Exponentendarstellung: Vorzeichen, 2 Dezimalziffern Das benutzte Rechenwerk verfüge auch nur über 5 Ziffern für den Signifikanden und 2 für den Exponenten, nicht darstellbare niederwertige Ziffern werden abgeschnitten. Beispiel: ( +23456, +7 ) + ( +28282, +4 ) = ( +23456, +7 ) + ( +00028, +7 ) = ( +23484, +7 ) Für Gleitpunktzahlen gelten nicht die üblichen algebraischen Gesetze, wie Assoziativgesetze und Distributivgesetze. Hier ein Beispiel für die Nichtgültigkeit des Assoziativgesetzes der Addition. u = ( +11113, +0 ) v = ( –11111, +0 ) w = ( +00075, –1 ) u + v = ( +00002, +0 ) v + w = ( –11104, +0 ) (u + v) + w = ( +00095, –1 ) u + (v + w) = ( +00009, +0 ) ≠ Bei Gleitpunktrechnungen bestimmt das gewählte Rechenverfahren die Größe des Rundungsfehlers, ein Beispiel: a b c d y = = = = = ( +1, −99) ( +2, −89) a ( +8, −89) ( +1, +11) dann a∗y + b c∗ y + d a∗y + b c∗ y + d = ( +12, − 89) = ( + 66666, − 5) ( + 18, − 89) b y d c+ y a+ = = ( +1, − 99) = ( + 1, + 0) ( + 1, − 99) Bemerkung: Ein C-Programm lieferte: Fall 1: Fall 2: 0.6666666666666667 0.6666666666666666 wobei nur Operanden im Format double benutzt wurden. Exponentenunterlauf: a = ( +5, −80 ) b = ( +2, +90 ) c := a / b ist nicht darstellbar, ein Näherungswert für c ist ( +0, +0 ) Exponentenüberlauf: a = ( +3, +80 ) b = ( +4, +90 ) c := a ∗ b ist nicht darstellbar. Der beste darstellbare Näherungswert für c wäre: c = ( +99999, +99 ), dieser Näherungswert wird aus ersichtlichen Gründen fast nie verwendet. /* Ein Beispiel für die Nichtgültigkeit der Assoziativ- und Distributivgesetze bei Gleitpunktrechnung. Die Rekursion X := (R + 1) * X - R * X^2 wird auf fünf verschiedene Arten berechnet. (1) (2) (3) (4) (5) X X X X X := := := := := (R + 1)*X - R*(X*X) (R + 1)*X - (R*X)*X ((R + 1) - R*X)*X R*X + (1 - R*X)*X X + R*(X - X*X) wobei R = 3,0 gesetzt und X mit 0,5 initialisiert wird. Das Beispiel stammt von Jean-Francois Colonna, der demonstrierte Effekt ist äußerst sensitiv gegenüber der Wahl des Parameters R. */ #include <iostream> #include <iomanip> using namespace std; typedef double REAL; int main () { int n = 10000, m = 1000; REAL x1, x2, x3, x4, x5; const REAL R = 3.0; const REAL INIT = 0.5; x1 = x2 = x3 = x4 = x5 = INIT; cout << endl << setw (5) << "k" << setw (12) << "x1" << setw (12) << "x2" << setw (12) << "x3" << setw (12) << "x4" << setw (12) << "x5" << endl; for (int k = 0; k <= n; ++k) { if (k % m == 0) cout << endl << setw (5) << k << setw (12) << x1 << setw (12) << x2 << setw (12) << x3 << setw (12) << x4 << setw (12) << x5; x1 = ( R+1)*x1 - R*(x1*x1); x2 = (R+1)*x2 - (R*x2)*x2; x3 = ((R+1) - R*x3)*x3; x4 = R*x4 + (1-R*x4)*x4; x5 = x5 + R*(x5 - x5*x5); } cout << endl; return 0; }//main /* Ausgabe: k x1 0 0.5 1000 1.33273 2000 1.05486 3000 1.04978 4000 0.0492222 5000 0.312817 6000 0.0562683 7000 0.323455 8000 1.00005 9000 1.26431 10000 1.14403 */ x2 x3 x4 x5 0.5 0.5 0.916561 1.20771 0.896127 0.685114 0.0219607 1.32874 1.32033 0.092438 1.32136 1.12155 1.33013 0.16467 0.111508 0.604536 0.870822 1.16909 0.0160684 0.000736023 1.32796 0.925377 0.5 0.277701 0.00922989 0.113546 0.949628 0.0420419 1.15916 0.984984 1.03379 1.11473 0.0701216 0.5 0.266633 0.386092 0.132707 1.3166 1.17097 1.25092 1.05838 0.930054 1.22268 1.31455 Gleitpunktzahlen in Binärdarstellung: Beispiele: 101 101101011 ∗ 2 10001 ,000101101011 ∗ 2 1011 101,101011 ∗ 2 Bemerkung: Die Darstellung von Gleitpunktzahlen ist nicht eindeutig. Oft wählt man daher eine feste Position für den Zahlpunkt, z. B. nach der ersten Nichtnullziffer. In diesem Fall spricht man von normalisierter Darstellung. Allgemeine Darstellung bei Signifikandenlänge n und Exponentenlänge m: ± B1 • B 2 B 3 B 4 ... B n ∗ 2 ± E1 E 2 ... E m Bemerkungen: (i) Statt 2 wählt man manchmal auch 8 oder 16 als Basis. (ii) Nach Möglichkeit speichert man nur normalisierte Gleitpunktzahlen ab. Im Falle der Basis 2 kann man die Speicherung eines Bit sparen. (iii) Den Exponenten speichert man oft in der Form einer Charakteristik ab: Charakteristik = Exponent + Versatz. Schutzziffern: Bei der Durchführung arithmetischer Operationen benutzt man zur Erhöhung der Rechengenauigkeit oft zusätzliche Stellen, sogenannte Schutzziffern. Beispiel: -5 1.0000 – 0.99999 = 10 Berechnung ohne Schutzziffern: ( +00001, − ( +99999, = ( +10000, − ( +09999, = ( +00001, +00 ) −05 ) −04 ) −04 ) −04 ) -4 = 10 Berechnung mit einer Schutzziffer: ( +00001 , − ( +99999 , = ( +10000 0, − ( +09999 9, = ( + 0000 1, +00 ) −05 ) −05 ) −05 ) −05 ) -5 = 10 Bemerkung: Schutzziffern erlauben die korrekte Implementation des folgenden Sachverhalts: sind a und b Gleitpunktzahlen mit 1/2 ≤ a/b ≤ 2, dann ist die Differenz a − b exakt darstellbar, falls kein Unterlauf eintritt. Runden: Man kennt drei Grundarten des Rundens: aufrunden, abrunden, zur "nächsten" Zahl runden. Beispiele: 10.8 10.8 10.8 ==> ==> ==> 11 aufrunden 10 abrunden 11 runden zur "nächsten" Zahl 10.5 nun existieren zwei Kandidaten als nächste Zahl, nämlich 10 und 11. Um ein sinnvolles Rundungsverfahren im Fall des Rundens zur nächsten Zahl zu finden, betrachtet man ein größeres Intervall: 10,1 10,5 10,6 11 11,1 11,5 11,6 bis 10,4 bis 10,9 bis 11,4 bis 11,9 ==> 10 ==> ? ==> 11 ==> 11 ==> ? ==> 12 Um ein neutrales Rundungsverfahren zu erhalten, sollte man die Fälle 10,5 und 11,5 unterschiedlich behandeln. Eine Möglichkeit besteht darin, daß im Falle zweier nächster Zahlen jeweils zur geraden Zahl gerundet wird. Beispiel zum Rundungsverhalten: Man betrachte ein Zahlsystem mit Basis 10 und Stellenzahl 3. Die Folge x0, x1, x2, . . . sei definiert durch: y x0 x1 x2 M xn M Fall 1: = = = = –0,555 1,00 (x0 – y) + y (x1 – y) + y = (xn–1 – y) + y Im Zweifelsfall aufrunden: x0 x1 x2 M x845 M xn = 1,00 = 1,56 – 0,555 = 1,01 = 1,02 = 9,45 = 9,45 für n ≥ 845 denn 9,45 + 0,555 = 10,0 und 10,0 – 0,555 = 9,45 Fall 2: Immer zur nächsten geraden Zahl runden: x0 x1 x2 M xn Fall 3: = = = (= = = 1,00 (1,00 + 0,555) – 0,555 1,56 – 0,555 1,005) 1,00 1,00 = 1,00 für n ≥ 0 Immer zur nächsten ungeraden Zahl runden: x0 x1 x2 M xn = = = = = = = 1,00 (1,00 + 0,555) – 0,555 1,55 – 0,555 0,995 (0,995 + 0,555) – 0,555 1,55 – 0,555 0,995 = 0,995 für n ≥ 1 Bemerkung: In diesem Beispiel liefert Fall 2 das beste Ergebnis. Im IEEE-Standard wird "Runden zum 'nächsten geraden' Wert" als Normalfall betrachtet. Bemerkungen zum ANSI/IEEE Standard 754–1985: "IEEE Standard for Binary Floating-Point Arithmetic" Nachdruck in Sigplan Notices 22, 2, pp 9–25 (1987) (i) Vier Genauigkeitsstufen: single, single extended, double, double extended (ii) Darstellungsformat: Vorzeichen Charakteristik Signifikand, hier für "single precision" 1 Bit 8 Bit 23 Bit V C S V Normalinterpretation: (–1) * 1.S * 2 C–127 Beispiel: 1 10000101 133–127 ≡ –1 * 2 00110000000000000000000 * 1.1875 = – 76 Bemerkung: Die 1 vor dem Binärpunkt wird nicht gespeichert. (iii) Sonderformate (nur für "single precision" erläutert) V 1 Bit C 8 Bit S 23 Bit +Null: –Null: 0 1 0 ... 0 0 ... 0 00 ... 0 00 ... 0 +∞: –∞: 0 1 1 ... 1 1 ... 1 00 ... 0 00 ... 0 Nichtzahlen (positive und negative): signalling: NaN: quiet NaN: signalling NaN: 0 0 M 0 1 M 1 1 1 ... 1 M M 1 ... 1 M 1 ... 1 1 ... 1 M 1 ... 1 1 ... 1 11 ... 11 M 01 ... 11 00 ... 01 00 ... 01 10 ... 00 M 11 ... 11 subnormale Zahlen (positive und negative): 0 M 0 1 M 1 0 ... 0 M 0 ... 0 0 ... 0 M 0 ... 0 11 ... 11 00 ... 01 00 ... 01 11 ... 11 (iv) Größenfestlegung für Formate: single single extended double double extended Genauigkeit in Bit 24 ≥ 32 53 ≥ 64 Größter Exponent 127 ≥1023 1023 ≥ 16383 Kleinster Exponent –126 ≤ –1022 –1022 ≤ –16382 Versatz 127 nicht spezifiziert 1023 nicht spezifiziert Das "single"–Format ist immer zu implementieren. (v) Subnormale Zahlen dienen dazu, einen gleitenden Übergang zur Null zu erreichen, außerdem bewahren sie die Identität: x = y <==> x – y = 0 –64 Beispiel: 2 –130 2 0 –66 *2 –130 = 2 dargestellt als subnormale Zahl 00000000 00010000000000000000000 (vi) Runden: Der IEEE Standard kennt vier Rundungsarten: Runden nach Null, Runden nach +∞, Runden nach –∞, Runden zum nächsten Wert (im Zweifelsfall zum geradzahligen). Beispiel bei Rechnung mit 4 Bit Genauigkeit: ==> ==> ==> – 5 * 10 = – 50 zu berechnen: Signifikandenprodukt: Ausrichten: 2 3 – 1.010 * 2 * 1.010 * 2 – 01100100 – 1100 | 1000 Runden nach Null: Runden nach +∞: Runden nach –∞: Runden zum nächsten Wert: – 1100 – 1100 – 1101 – 1100 Ergebnis bei Runden nach Null: Runden nach +∞: Runden nach –∞: Runden zum nächsten Wert: 5 –1.100 * 2 5 –1.100 * 2 5 –1.101 * 2 5 –1.100 * 2 = = = = –48 –48 –52 –48 Die verschiedenen Rundungsarten gestatten die Implementation einer Intervall-Arithmetik. (vii) Bei der Implementation der Rechenoperationen erwartet der IEEE Standard drei Hilfsbit: Guard Bit, Round Bit, Sticky Bit. Erläuternde Beispiele: 6 Bit Genauigkeit, Exponentendifferenz 5: + 1.10011 0.00001 1.10100 10001 Zur korrekten Rundung des Ergebnisses benötigt man das Wissen, daß jenseits des ersten nicht in der Addition berücksichtigten Bit noch ein weiteres Nichtnullbit existiert (codiert im "sticky bit"). Das korrekte Resultat bei Rundung zum nächsten Wert ist 1.10101. 6 Bit Genauigkeit, Exponentendifferenz 2: 1.11011 + 0.01010 10.00101 01 Ergebnis bei Rundung zum nächsten Wert: 10.0011 6 Bit Genauigkeit, Exponentendifferenz 6: – ==> + 1.00000 0.00000 101111 1.00000 1.11111 010001 0.11111 Gerundetes Resultat ist: 0.111111 (viii) Es wird eine Restfunktion REM für Gleitpunktzahlen definiert durch: x = [ x/y] * y + (x REM y) mit | x/y - [x/y] | ≤ 1/2 Im Konfliktfall wird zur nächsten geraden Ganzzahl gerundet. Die Restfunktion ist sinnvoll bei der Berechnung trigonometrischer Funktionen. (ix) Für Nichtzahlen und unendlich werden die Rechenregeln sinnvoll ergänzt, z.B. NaN + Zahl = NaN Zahl / 0 = ± ∞, falls keine "Exception" ausgelöst wird; das Vorzeichen von ∞ ist das algebraisch korrekte. Kahans Summationsalgorithmus: Aufgabe: Sei a ein Array von n Gleitpunktzahlen, man berechne die Summe dieser n Zahlen möglichst genau. In Formeln: Gleitpunkttyp a [n]; n−1 Summe = ∑ a [i] i=0 Als C++ - Text: template <class T> T kahansum (T x [], int laenge) { // Annahme: laenge >= 1 T korr = 0; T sum = x [0]; for (int i = 1; i < laenge; ++i) { T y = x [i] - korr; T t = sum + y; korr = t - sum; korr = korr - y; sum = t; } return sum; }//kahansum Beispiel auf einer Sparc Ultra: Kahans Summe (24 Bit Genauigkeit) = 5.220937318e+10 Einfache Summe (24 Bit Genauigkeit) = 5.22094592e+10 Einfache Summe (53 Bit Genauigkeit) = 5.220937515e+10 Einfache Summe (113 Bit Genauigkeit) = 5.220937515e+10 Graphische Erläuterung zu Kahans Algorithmus: Schritt 1: s yh + yl t Schritt 2: t – s yh Schritt 3: yh – Korrektur: yh yl – yl Zahlwandlung von Gleitpunktzahlen: Im Single-Format des IEEE-Standards verwendet man zur Beschreibung des Signifikanden 24 Bit. Aus der Ungleichung 24 2 8 = 16.777.216 < 100.000.000 = 10 darf man nicht schließen, daß 8 Dezimalziffern zur eindeutigen Darstellung des Signifikanden im Dezimalsystem ausreichen. Es gilt vielmehr: Zur eindeutigen Repräsentation von 24 Binärziffern benötigt man 9 Dezimalziffern. Beweis: Man betrachte das halboffene Intervall [1000, 1024), dann 14 fallen in dieses Intervall 24 * 2 = 393.216 Binärzahlen mit 24 Binärziffern, aber nur 240.000 Dezimalzahlen mit 8 Ziffern; daher benötigt man mindestens 9 Dezimalziffern. Es seien nun 9 Dezimalziffern gegeben. Man betrachte das n n+1 Intervall [10 , 10 ), der Abstand zweier Dezimalzahlen n+1-9 n m . Sei m minimal mit 10 < 2 ; der ist dann 10 m-24 ; nun gilt Abstand der Binärzahlen ist 2 (n+1)-9 n -8 m -24 10 = 10 * 10 < 2 * 2 . q.e.d. Relativer Fehler: Man betrachte ein Zahlensystem mit Basis B und Signifikandenlänge p. Satz: Der relative Fehler bei der Ausführung einer Addition kann bis B − 1 reichen. Beweis: Seien x = 1.000 . . . 000 y = − 0.aaa . . . aaaa mit a = B − 1 p Ziffern -p exakte Summe = B -p+1 berechnete Summe = B -p+1 relativer Fehler = (B -p -p − B )/B = B−1 Bemerkung: Obiger Satz zeigt, daß bei Gleitpunktrechnungen im Dualsystem in der Tendenz die kleinsten relativen Fehler begangen werden. Zahlausgabe: e Sei G = {g / g = s * b mit s besteht aus genau p > 0 b-Ziffern und s ≥ 0 und e eine Ganzzahl} Bem.: Jede Zahl aus G hat einen eindeutigen Nachfolger + − g und bis auf 0 einen eindeutigen Vorgänger g . Gesucht ist ein Algorithmus, der zu jeder Zahl g ≠ 0 aus k G eine Zahl z = 0.d1d2d3 . . . dn * B bestimmt mit d1, d2, d3, . . . , dn sind B-Ziffern und n ist die kleinste Ganzzahl, so daß gilt: g + g+ g− + g < z < 2 2 (i ) |z − g| ≤ ( ii ) 1 ∗ Bk − n 2 Veranschaulichung: − g − (g +g)/2 g + (g+ g )/2 + g Bemerkung: Alle Zahlen im schraffierten Bereich der Zahlachse sind in G nicht unterscheidbar. Daher ist es sinnvoll, zur Darstellung von z als B-Zahl die B-Zahl mit der geringsten Ziffernzahl zu wählen. Algorithmus: − + 1. Zu g bestimme lg = (g +g) / 2 und rg = (g+ g ) / 2. k 2. Bestimme kleinstes k mit rg ≤ B . k 3. Setze q0 = g / B . 4. Bilde Folgen d1 = q0 * B d2 = q1 * B d3 = q2 * B d4 = q3 * B M q1 q2 q3 q4 = = = = M q0 * B q1 * B q2 * B q3 * B − − − − d1 d2 d3 d4 5. Beende die Erzeugung von Ziffern mit dem kleinsten n, für daß (i) oder (ii) gilt: k > lg (i) 0.d1d2d3 . . . dn * B k (ii) 0.d1d2d3 . . . (dn +1) * B < rg Gilt (i) und nicht (ii), dann ist das Ergebnis die B-Zahl aus (i). Gilt (ii) und nicht (i), dann ist das Ergebnis die B-Zahl aus (ii). Gelten sowohl (i) als auch (ii), dann wähle als Ergebnis eine B-Zahl, die den geringsten Abstand von z hat. Bemerkung: Der obige Algorithmus läßt sich so transformieren, daß er nur mit Ganzzahlen implementierbar wird. Satz: Es gilt: (i) 0 ≤ di < B für i = 1, 2, 3, . . ., (ii) d1 > 0, (iii) wird dn inkrementiert, dann führt das nicht zu einem Übertrag. Beweis: k k Es gilt: 0 < q0 = g / B < 1, da 0 < g < rg ≤ B . Für i ≥ 1 gilt: 0 ≤ qi < 1 gemäß Bildung von qi. Somit 0 ≤ qi * B < B, hieraus folgt unmittelbar (i). k k-1 < rg, es gilt Sei d1 = 0, dann 0.(d1+1) * B = B Endebedingung (ii) und wegen d1 = 0 nicht (1). Damit ist jedem Fall d1 > 0. k k Sei d1 = B-1, dann 0.(d1+1) * B = B ≥ rg, daher gilt Endebedingung (ii) nicht und d1 wird nicht inkrementiert. Sei bei Algorithmusende die letzte Ziffer dn für n > 1 gleich B-1, dann gilt: k k 0.d1d2d3 . . . (dn+1)*B = 0.d1d2d3 . . . (dn-1 +1)*B < rg. Der Algorithmus wäre schon im Schritt n-1 beendet worden, was im Widerspruch zur Annahme, dn ist die letzte Ziffer steht. Bemerkung: Den Beweis für die übrigen Eigenschaften des Algorithmus führt man analog. Lange Ganzzahlarithmetik: Zerlegung einer Zahl in Zifferngruppen: Beispiel: 37268914538479725419437 = 37 268 914 538 479 725 419 437 Bemerkung: Bei einer Implementation langer Zahlen verteilt man die Zifferngruppen auf einen Array von Ganzzahlen. Die Programmierung der Operationen Addition, Subtraktion, Multiplikation ist einfach; einziges Problem ist die Programmierung der Division, genauer die Schätzung einer Divisionsziffer. Schätzung einer Divisionsziffer: Vor.: Sei b eine Basis mit b ≥ 2, seien u und v Zahlen zur Basis b n n–1 + . . . + un mit u = u0∗b + u1∗b n–1 und v = v1∗b + . . . + vn (v1 ≠ 0), sei u / v < b, sei q = u div v, sei qs = min ((u0∗b + u1) div v1, b – 1). Beh. 1: q ≤ qs Bew.: Fall 1: qs = b – 1, dann q ≤ qs, da q < b. Fall 2: qs = (u0∗b + u1) div v1 Nun qs∗v1 ≥ u0∗b + u1 – (v1 – 1) damit n–1 u – v∗qs ≤ u – v1∗b ∗qs n ≤ u0∗b + u1∗b n n–1 + . . . + un n–1 – (u0∗b + u1∗b – v1∗b n-2 + . . . + un – b n-1 ≤ v = u2∗b < v1∗b n-1 n-1 + b n-1 ) n–1 + v1∗b Es folgt q ≤ qs, da u < v∗qs + v und somit q ≤ u / v < qs + 1 q.e.d. Beh. 2: v1 ≥ b div 2 ==> qs – 2 ≤ q ≤ qs Bew. indirekt: Sei q + 3 ≤ qs, nun: u 0 ∗ b + u1 u 0 ∗ b n + u1 ∗ b n − 1 = qs ≤ v1 v1 ∗ b n −1 ≤ u v1 ∗ b n −1 n–1 Hier v ≠ b < u v − b n −1 , da sonst qs = q, Widerspruch! Ferner gilt: q > u / v – 1, nun: 3 ≤ qs − q < u v − b n −1 u b n −1 = ∗ v v − b n −1 − u + 1 v + 1 ==> u v − b n −1 > 2∗ v b n −1 ≥ 2 ∗ ( v1 − 1) Nun: b – 1 ≥ qs b – 4 ≥ qs – 3 ≥ q ≥ 2 ∗ (v1 – 1) b – 4 ≥ 2 ∗ v1 – 2 b – 2 ≥ 2 ∗ v1 b / 2 – 1 ≥ v1 b div 2 > v1 Widerspruch!