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!