-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathblatt05.cpp
More file actions
130 lines (108 loc) · 3.44 KB
/
blatt05.cpp
File metadata and controls
130 lines (108 loc) · 3.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include <iostream>
#include <iomanip>
#include <cerrno>
#include <cstring>
using namespace std;
/// Konstante, die die Zahl 10...0 beschreibt.
unsigned const HI_BIT = compl (compl 0u >> 1);
/// Schreibt die Bits von u auf die Standardausgabe.
void printbits(unsigned u)
{
for (unsigned testBit = HI_BIT; testBit != 0u; testBit >>= 1)
cout << (u & testBit ? '1' : '0');
}
/// Addiert a und b.
unsigned add_1a(unsigned a, unsigned b)
{
unsigned h = a ^ b, // Halbaddition
u = a & b; // Prä-Übertrag
if (u == 0u) return h; // Trivialen Fall abfangen.
if (u & HI_BIT) // Auf Überlauf testen (Prä-Übertrag hat ganz vorne eine 1)
{
errno = ERANGE;
return 0u;
}
// Mit Endrekursion Ergebnis auf trivialen Fall reduzieren.
return add_1a(h, u << 1);
}
/// Addiert a und b.
unsigned add_1b(unsigned a, unsigned b)
{
begin:
unsigned h = a ^ b, // Halbaddition
u = a & b; // Prä-Übertrag
if (u == 0u) return h; // Trivialen Fall abfangen.
if (u & HI_BIT) // Auf Überlauf testen (Prä-Übertrag hat ganz hinten eine 1)
{
errno = ERANGE;
return 0u;
}
a = h; // |
b = u << 1; // > Endrekursion aufgelöst.
goto begin; // |
}
/// Addiert a und b.
unsigned add_2(unsigned a, unsigned b)
{
while (b != 0)
{
unsigned h = a ^ b, // Berechnen...
u = a & b; // ...wie oben.
if (u & HI_BIT) // Fehlerbehandlung wie oben.
{
errno = ERANGE;
return 0u;
}
a = h; // Für den nächsten Schritt a und b...
b = u << 1; // ...auf die entsprechenden Werte setzen.
}
return a;
}
/// Multipliziert a und b.
unsigned mult(unsigned a, unsigned b)
{
unsigned sum = (a & 1u) ? b : 0u; // Summe initialisieren.
// a nach rechts schieben, d. h. nächstes Bit verarbeiten.
while ((a >>= 1) != 0u)
{
// Ab hier gilt a != 0, laut Schleifenbedingung.
if (b & HI_BIT) // Da a != 0 gilt, muss dies einen Überlauf darstellen.
{
errno = ERANGE;
return 0u;
}
b <<= 1; // b nach links schieben, d. h. verdoppeln.
if (a & 1u) // Falls das unterste Bit von a gesetzt ist...
{ // ...b zur Summe hinzuaddieren.
sum = add_2(sum, b);
if (errno) return 0u; // Evtl. auftretenden Fehler fangen und propagieren.
}
}
return sum;
}
int main()
{
// a und b einlesen.
cout << "a, b (hexadezimal): " << flush;
unsigned a, b;
cin >> hex >> a >> b;
// Multiplikation mit Fehlerbehandlung durchführen
errno = 0;
unsigned m = mult(a, b);
switch (errno)
{
case 0: // Fehlerfreier Aufruf.
cout << "Dezimal:\n" << dec
<< "mult(a, b) = " << m << '\n'
<< "a * b = " << (a * b) << '\n' << endl;
cout << "Hexadezimal:\n" << hex;
cout << "mult(a, b) = " << m << '\n'
<< "a * b = " << (a * b) << '\n' << endl;
break;
case ERANGE: // Wertebereichsfehler, d. h. Überlauf. Damit ist zu rechnen.
cout << "Überlauf!" << endl;
break;
default: // bei anderen Fehlern können wir a-priori keine Ursache angeben.
cout << "Unerwartete Ausnahme. Details: " << strerror(errno) << endl;
}
}