====== Zahlensysteme ======
Dossier: {{ :gf_informatik:gfif_zahlensysteme_dossier.pdf |}}
++++ Lernziele|
Prüfungsrelevant ist alles, was in den Lektionen und Übungen behandelt wurde. Die Lernziele unten dienen als Gradmesser und sind nicht unbedingt komplett.
**Erklären:**
* Was ist ein Zahlensystem? Erkläre mit Fachbegriffen.
* Warum ist das Binärsystem wichtig in der Informatik?
* Was bedeutet die Bit-Zahl bei einer Computerarchitektur?
* Interpretation von (Binär-)Zahlen: Wie kann man eine gegebene Zahl auf verschiedene Arten interpretieren?
* Wie stellt man negative Zahlen binär dar? Warum macht man das genau so?
* Warum Hexadezimalsystem sehr praktisch ist, wenn man mit Binärzahlen arbeitet
**Rechnen:**
von Hand und direkt (also nicht z.B. vor Addition in 10er-System umrechnen):
* Umrechnen binär -> dezimal
* Uhrzeit von Binäruhr bestimmen
* Umrechnen dezimal -> binär
* binär addieren
* 2er-Komplement bestimmen
* binär subtrahieren
* binär multiplizieren
* direkt Umrechnen binär <-> hexadezimal
* umrechnen: hexadezimal <-> dezimal
**Code:**
* Umrechnen binär -> dezimal
* Umrechnen dezimal -> binär
* binär addieren
* 2er-Komplement bestimmen (verwende binäre Addition)
* binär subtrahieren (verwende 2er-Komplement und binäre Addition)
++++
==== Zusätzliche Infos ====
==== Erklärung negative Binärzahlen & Subtraktion ====
=== Negative Zahlen & 2er-Komplement ===
Computer arbeiten immer mit fixen Bitlängen. Zum Beispiel sind moderne Computer 64-Bit Computer. Das heisst, sie rechnen intern immer mit Zahlen mit einer Länge von 64 Bit.In den 80er-Jahren hingegen war 8-Bit der Standard. Lass uns einen solchen betrachten:
Möchte ein solcher Computer die Dezimalzahl 42 speichern, so speichert er die Binärzahl $0010\,1010$. Beachte,
dass die beiden Nullen links eigentlich unnötig sind, aber es müssen immer alle Bits gesetzt sein. Ein solcher Computer kann insgesamt $2^8 = 256$ verschiedene Zahlen darstellen. Wenn man einen Computer hat, der nur mit positiven ganzen Zahlen rechnen soll, ist die kleinste Zahl $0000\,0000 = 0$ und die grösste $1111\,1111 = 255_{10}$. Wenn man aber einen Computer haben möchte, der sowohl positive als auch negative Zahlen darstellen kann, müssen sich die positiven und negativen Zahlen die $256$ möglichen Plätze *teilen*. Der Fairness halber macht es Sinn, dass die positiven und negativen Zahlen jeweils die Hälfte der möglichen Plätze erhalten.
Es wird dann so gemacht, dass positive Zahlen mit einer $0$ links beginnen und negative Zahlen mit einer $1$. Die Dezimalzahl $+42$ wäre dann also die Binärzahl $0010\,1010$. Die positiven Zahlen gehen dann also von $0000\,0000 = 0$ bis $0111\,1111 = 127$. Es ist also *nicht* möglich, auf einem solchen Computer die Zahl $200$ zu speichern!
Doch welcher Dezimalzahl entspricht $1010\,1010$? Auf den ersten Blick mag es Sinn machen, zu denken, dass dies die Dezimalzahl $-42$ sei. Doch dies führt zu einem Problem: Addiert man die beiden Zahlen, so erhält man *nicht Null*:
$$0010\,1010 + 1010\,1010 = 1101\,0100$$
Stattdessen geht man wie folgt vor, um von einer Zahl (z.B. $42_{10} = 10\,1010$) die Gegenzahl ($-42_{10} = ???$) zu finden:
1. **Bits hinzufügen:** Füge links gegebenenfalls $0$ hinzu, so dass Zahl gewünschte Länge hat. Denke daran: Positive (negative) Zahlen haben links eine 0 (1). Da wir einen $8-$Bit Computer betrachten also:
$$0010\,1010$$
1. **Invertieren:** Nullen werden zu Einsen, Einsen zu Nullen:
$$1101\,0101$$
1. **Eins Addieren:** Rechne $+1$:
$$1101\,0110$$
Dementsprechend gilt also $-42_{10} = 1101\,0110$, *falls* wir $8-$Bit Zahlen inkl. negative Zahlen betrachten. Ohne diese Information würde man die Zahl wohl als die positive Zahl $214_{10}$ interpretieren. Man muss also immer ganz klar sagen, *wie man eine jeweilige Zahl zu interpretieren hat!*
=== Subraktion ===
**Beispiel 1:** Wir wollen in $8$-Bit die folgende Subtraktion durchführen:
$$0110\,1001 - 0001\,1101 = ?$$
Bei der Subtraktion wird die erste Zahl Minuend, die Zweite Subtrahend genannt.
1. Zuerst müssen wir mithilfe des 2er-Komplements die Gegenzahl vom Subtrahend bestimmen (Invertieren, $+1$): $1110\,0011$
1. Addiere Minuend mit 2er-Komplement von Subtrahend: $$0110\,1001 + 1110\,0011 = 1\,0100\,1100$$
1. Beachte, dass wir ein $9.$ Bit aufgelesen haben. Ein $8-$Bit Computer kann dieses aber gar nicht erst speichern und es geht einfach verloren, also ist das Resultat:
$$0110\,1001 - 0001\,1101 = 0100\,1100$$
**Beispiel 2:** Wir wollen berechnen: $$1\,1011 - 101 = ?$$
Beachte, dass hier *keine* Angaben bzgl. Anzahl Bits gemacht werden. Wir fassen deshalb beide Zahlen ($1\,1011$ und $101$) als *positive* Zahlen, auch wenn die Bits ganz links eine $1$ sind. Deshalb müssen wir die beiden Zahlen so erweitern, dass:
1. beide gleich lang sind
1. beide links (mind.) eine $0$ haben
Also notieren also beide Zahlen als $6-$Bit Zahlen:
$$01\,1011 - 00\,0101 = ?$$
Jetzt können wir vorgehen wie in Beispiel 1:
1. 2-er Komplement (Invertieren, $+1$): $11\,1011$
1. Addieren: $$01\,1011 + 11\,1011 = 101\,0110$$
1. Zusätzliches 7. Bit ignorieren. Da keine feste Bitzahl angegeben wurde, kann man auch noch die Nullen links ignorieren. Resultat ist also: $$1\,1011 - 101 = 1\,0110$$
$$01\,1011 - 00\,0101 = ?$$
=== Tipps: Code binäre Subtraktion ===
1. Implementiere die Inversion (Umkehrung) einer Binärzahl, optimalerweise in einer eigenen Funktion.
1. 2er-Komplement: Verwende dazu deinen Code/deine Funktion von 1. und addiere dann "1" dazu. Dazu kannst du deine `binary_add()`-Funktion von früher verwenden.
1. Addiere zum Minuend das 2er-Komplement des Subtrahends. Verwende dazu wieder die `binary_add()`.
===== Lösungen =====
++++Binary to Decimal|
Verschiedene Versionen:
def binary_to_decimal_1(b):
d = 0 # decimal nr
i = 0
while i < len(b):
d = d + int(b[len(b)-i-1]) * 2**i # len(b)-i-1 to go through b in reverse order
i = i + 1
return d
def binary_to_decimal_2(b):
d = 0 # decimal nr
i = 0
while i < len(b):
d = d + int(b[-i-1]) * 2**i # can also use negative indices to go through d in reverse order
i = i + 1
return d
def binary_to_decimal_3(b):
d = 0 # decimal nr
i = len(b) - 1
power = 1
while i >= 0:
d = d + int(b[i]) * power
power = power * 2
i = i - 1
return d
++++
++++Decimal to Binary|
def decimal_to_binary(d):
b = ''
while d > 0:
b = str(d % 2) + b
d = d // 2
return b
++++
++++Binary Operations|
def binary_add(b1,b2):
b1 = b1.replace(" ","") # remove all blanks
b2 = b2.replace(" ","") # remove all blanks
# make sure strings have same length
while len(b1) < len(b2):
b1 = '0' + b1
while len(b1) > len(b2):
b2 = '0' + b2
# add binary string
summe = ''
i = len(b1) - 1
carry = '0'
while i >= 0:
if b1[i] == '0' and b2[i] == '0' and carry == '0':
summe = '0' + summe
carry = '0'
elif b1[i] == '1' and b2[i] == '1' and carry == '1':
summe = '1' + summe
carry = '1'
elif (b1[i] == '1' and b2[i] == '1' and carry == '0') or (b1[i] == '1' and b2[i] == '0' and carry == '1') or (b1[i] == '0' and b2[i] == '1' and carry == '1'):
summe = '0' + summe
carry = '1'
else:
summe = '1' + summe
carry = '0'
i = i - 1
if carry == '1':
summe = '1' + summe
return summe
def invert(b):
b = b.replace(" ","") # remove all blanks
inv = ""
i = 0
while i < len(b):
if b[i] == '0':
inv = inv + '1'
else:
inv = inv + '0'
i = i + 1
return inv
def complement(b):
b = b.replace(" ","") # remove all blanks
b = invert(b)
b = binary_add(b,'1')
return b
def binary_sub(b1,b2): # calc b1-b2
b1 = b1.replace(" ","") # remove all blanks
b2 = b2.replace(" ","") # remove all blanks
# make sure strings have same length
while len(b1) < len(b2):
b1 = '0' + b1
while len(b1) > len(b2):
b2 = '0' + b2
# add additional zero at left (to distinguish between positive and negative numbers)
b1 = '0' + b1
b2 = '0' + b2
result = binary_add(b1,complement(b2))
result = result[1:] # remove first bit
while len(result) > 1 and result[0] == '0': # remove all zeros at beginning (optional)
result = result[1:]
return result
def binary_mul(b1,b2):
b1 = b1.replace(" ","") # remove all blanks
b2 = b2.replace(" ","") # remove all blanks
result = ""
i = len(b1) - 1
while i >= 0:
if b1[i] == '1':
result = binary_add(result,b2)
b2 = b2 + '0'
i = i - 1
while len(result) > 1 and result[0] == '0': # remove all zeros at beginning
result = result[1:]
return result
++++
===== Lösungen Code für Lehrpersonen =====
++++Lösung|
def binary_to_decimal(b):
n = len(b)
d = 0 # decimal number
for i in range(n):
d = d + int(b[i]) * 2**(n-i-1)
return d
def decimal_to_binary(d,bits=None):
b = ""
while d > 0:
b = str(d%2) + b
d //= 2
if bits:
while len(b) < bits:
b = '0' + b
return b
def binary_add(a,b):
# PREPARE NUMBERS
a = a.replace(" ","") # remove blanks
b = b.replace(" ","")
# ADD 0 TO HAVE SAME LENGTH
while len(a) < len(b): a = "0" + a
while len(b) < len(a): b = "0" + b
# ADD NUMBERS
n = len(a)
out = "" # string mit Resultat
rest = 0
for i in range(n):
k = n-1-i
summe = int(a[k])+int(b[k])+rest
out = str(summe%2) + out
rest = summe // 2
if rest != 0:
out = str(rest) + out
return out
def binary_add_list(L):
# adds all binary numbers in list L
b = L[0]
for i in range(len(L)-1):
b = binary_add(b,L[i+1])
return b
def binary_invert(a):
a = a.replace(" ","") # remove blanks
out = ""
for c in a:
if c == "0":
out += "1"
else:
out += "0"
return out
def binary_complement(a,bits=None):
a = a.replace(" ","") # remove blanks
if bits == None: bits = len(a)
while len(a) < bits:
a = "0" + a
out = binary_add(binary_invert(a),"1")
if len(out) > bits:
out = out[1::]
return out
def binary_sub(a,b):
a = a.replace(" ","") # remove blanks
b = b.replace(" ","")
while len(a) < len(b): a = "0" + a
while len(b) < len(a): b = "0" + b
bits = len(a)
# extend by one bit
a = "0" + a
b = "0" + b
out = binary_add(a,binary_complement(b))
return out[len(out)-bits::] # make sure to cut right number of bits from left side
def binary_mult(a,b):
# PREPARE NUMBERS
a = a.replace(" ","") # remove blanks
b = b.replace(" ","")
out = ""
for i in range(len(a)):
j = len(a)-1-i
if a[j] == "1":
out = binary_add(out,b + i*"0")
# remove zeros on left side
while out[0] == "0" and len(out) > 1:
out = out[1::]
return out
print(binary_to_decimal("0010000100"))
print(decimal_to_binary(42))
print(binary_add("10101010","101000"))
print(binary_complement("00101101"))
print(binary_sub("1000 0000","0001 1111"))
print(binary_sub("1010 1011","0110 1011"))
print(binary_sub("1111 0010","1000 1111"))
# binary multiplication
print(binary_mult("1101","1111") == "11000011")
print(binary_mult("10010010","01100011") == "11100001110110")
print(binary_mult("11111011","11101011") == "1110011001101001")
print(binary_mult("1100101100111101","1110011101111010") == "10110111110001001110011000010010")
++++
++++Function Testing|
### FUNCTION TESTING CODE
for i in range(1000):
da = random.randint(0,165)
db = random.randint(0,165)
if db > da: da,db = db,da
a = bin(da)[2:]
b = bin(db)[2:]
if not a == invert(invert(a)):
print("ERROR Invert: ",a,invert(a))
if not binary_add(a,b) == bin(int(a,2)+int(b,2))[2:]:
print("ERROR Add: ",a,b)
if not binary_sub(a,b) == bin(int(a,2)-int(b,2))[2:]:
print("ERROR Sub: ",a,b)
++++
++++Exercise Generator|
### EXERCISE GENERATOR
for i in range(3):
da = random.randint(128,256)
db = random.randint(128,256)
if db > da: da,db = db,da
a = bin(da)[2:]
b = bin(db)[2:]
print("Berechne schriftlich von Hand (Bemerkung & isPencil-Feld), trage Resultat ins Antwortfeld ein:\n" + a + " + " + b )
print("LOESUNG: " + binary_add(a,b) + "\n")
for i in range(3):
da = random.randint(128,256)
a = bin(da)[2:]
print("Berechne schriftlich von Hand (Bemerkung & isPencil-Feld), trage Resultat ins Antwortfeld ein. 2-er Komplement in 8-Bit von:\n" + a)
print("LOESUNG: " + binary_complement(a) + "\n")
for i in range(3):
da = random.randint(128,256)
db = random.randint(128,256)
if db > da: da,db = db,da
a = bin(da)[2:]
b = bin(db)[2:]
print("Berechne schriftlich von Hand (Bemerkung & isPencil-Feld), trage Resultat ins Antwortfeld ein. Lasse überflüssige Nullen auf linker Seite weg.\n" + a + " - " + b )
print("LOESUNG: " + binary_sub(a,b) + "\n")
for i in range(3):
da = random.randint(1,15)
db = random.randint(1,15)
if db > da: da,db = db,da
a = bin(da)[2:]
b = bin(db)[2:]
while len(a) < 4: a = '0' + a
while len(b) < 4: b = '0' + b
print("Berechne schriftlich von Hand (Bemerkung & isPencil-Feld), trage Resultat ins Antwortfeld ein.\n" + a + " * " + b )
print("LOESUNG: " + bin(da*db)[2:] + "\n")
++++