Programmieren mit Harald R. Haberstroh (original) (raw)
Montag, 6. Juni 2011
Listings - Source Code drucken
Es sollte m.E. doch möglich sein, Listings in der folgenden - lesbaren - Form zu erzeugen:
Die Schrift ist leserlich, die Zeilen richtig eingerückt, Dateiname und Autor etc. sind ersichtlich (Ich gebe zu, dieses Bild ist schlecht...). Verwendet wurde recode und a2ps unter Linux.
Aber mit Office kann man auch sehr schöne Listings erzeugen:
Man muss nur Kopf- und Fußzeilen einrichten, die Schrift auf Courier New (9 oder 10pt) oder eine andere mit fixer Breite und dann zwei Seiten auf eine drucken.
Stattdessen bekommt man so etwas.
Der Sourcecode ist unmöglich zu lesen, weil die Einrückung bald die dargestellte Zeilenlänge erreicht. Die Schriftgröße ist aber zumindest OK.
Schlimm ist aber das folgende Listing, da würden 4 Code-Seiten auf einem Blatt Platz haben. Trotzdem sind es aber nur 2 Seiten pro Blatt. Die Schrift ist unleserlich klein.
Das ist eine Zumutung!
Labels: allgemeines, POS1-1, POS1-2, PR2, PR3, PR5
Mittwoch, 27. April 2011
Beispiele zu Gleitkommadarstellung (POS1: 1B)
Hier finden Sie ein paar Übungsbeispiele zu Gleitkommazahlen sowie die dazugehörige Lösung. Zunächst Konvertierung von Dezimalzahlen in Gleitkommazahlen. Es sind die Zahlen immer alle drei Formate zu bestimmen:
-0,15087890625
Nachkommateil: 0.15087891 | 0 0.30175781 | 0 0.60351562 | 1 0.20703125 | 0 0.41406250 | 0 0.82812500 | 1 0.65625000 | 1 0.31250000 | 0 0.62500000 | 1 0.25000000 | 0 0.50000000 | 1 Gesamt: 1 ,00100110101 (die 1 steht für das Vorzeichen -) Mantisse wäre: 1001101010 Exponent wäre: -2 Exponent umwandeln: 2 | 0 1 | 1 Exponent unbeschränkt positiv: 10 Exponent mit führenden Nullen: 0010 Zweierkomplement: Einerkomplement: 1101 1 Zweierkomplement: 1110 Exponent: 1110, Vorzeichen: 1
vm m m m m m m m m m m ve e e e e
1 1 0 0 1 1 0 1 0 1 0 1 1 1 1 0
vm ve e e e e m m m m m m m m m m
1 1 1 1 1 0 1 0 0 1 1 0 1 0 1 0
ve e e e e vm m m m m m m m m m m
1 1 1 1 0 1 1 0 0 1 1 0 1 0 1 0
33
ganzzahliger Teil: 33 | 1 16 | 0 8 | 0 4 | 0 2 | 0 1 | 1 Nachkommateil: Gesamt: 0 100001, (die 0 steht für das Vorzeichen + - beachte den Abstand) Mantisse wäre: 1000010000 Exponent wäre: 6 Exponent umwandeln: 6 | 0 3 | 1 1 | 1 Exponent unbeschränkt positiv: 110 Exponent: 0110, Vorzeichen: 0
vm m m m m m m m m m m ve e e e e
0 1 0 0 0 0 1 0 0 0 0 0 0 1 1 0
vm ve e e e e m m m m m m m m m m
0 0 0 1 1 0 1 0 0 0 0 1 0 0 0 0
ve e e e e vm m m m m m m m m m m
0 0 1 1 0 0 1 0 0 0 0 1 0 0 0 0
470,171875
ganzzahliger Teil: 470 | 0 235 | 1 117 | 1 58 | 0 29 | 1 14 | 0 7 | 1 3 | 1 1 | 1 Nachkommateil: 0.17187500 | 0 0.34375000 | 0 0.68750000 | 1 0.37500000 | 0 0.75000000 | 1 0.50000000 | 1 Gesamt: 0 111010110,001011 Mantisse wäre: 1110101100 Exponent wäre: 9 Exponent umwandeln: 9 | 1 4 | 0 2 | 0 1 | 1 Exponent unbeschränkt positiv: 1001 Exponent: 1001, Vorzeichen: 0
vm m m m m m m m m m m ve e e e e
0 1 1 1 0 1 0 1 1 0 0 0 1 0 0 1
vm ve e e e e m m m m m m m m m m
0 0 1 0 0 1 1 1 1 0 1 0 1 1 0 0
ve e e e e vm m m m m m m m m m m
0 1 0 0 1 0 1 1 1 0 1 0 1 1 0 0
-17,2145
ganzzahliger Teil: 17 | 1 8 | 0 4 | 0 2 | 0 1 | 1 Nachkommateil: 0.21450000 | 0 0.42900000 | 0 0.85800000 | 1 0.71600000 | 1 0.43200000 | 0 0.86400000 | 1 0.72800000 | 1 0.45600000 | 0 0.91200000 | 1 0.82400000 | 1 0.64800000 | 1 0.29600000 | 0 0.59200000 | 1 0.18400000 | 0 0.36800000 | 0 0.73600000 | 1 0.47200000 | 0 0.94400000 | 1 Gesamt: 1 10001,001101101110100101 Mantisse wäre: 1000100110 Exponent wäre: 5 Exponent umwandeln: 5 | 1 2 | 0 1 | 1 Exponent unbeschränkt positiv: 101 Exponent: 0101, Vorzeichen: 0
vm m m m m m m m m m m ve e e e e
1 1 0 0 0 1 0 0 1 1 0 0 0 1 0 1
vm ve e e e e m m m m m m m m m m
1 0 0 1 0 1 1 0 0 0 1 0 0 1 1 0
ve e e e e vm m m m m m m m m m m
0 0 1 0 1 1 1 0 0 0 1 0 0 1 1 0
-0,015625
ganzzahliger Teil: Nachkommateil: 0.01562500 | 0 0.03125000 | 0 0.06250000 | 0 0.12500000 | 0 0.25000000 | 0 0.50000000 | 1 Gesamt: 1 ,000001 Mantisse wäre: 1000000000 Exponent wäre: -5 Exponent umwandeln: 5 | 1 2 | 0 1 | 1 Exponent unbeschränkt positiv: 101 Exponent mit führenden Nullen: 0101 Zweierkomplement: Einerkomplement: 1010 1 Zweierkomplement: 1011 Exponent: 1011, Vorzeichen: 1
vm m m m m m m m m m m ve e e e e
1 1 0 0 0 0 0 0 0 0 0 1 1 0 1 1
vm ve e e e e m m m m m m m m m m
1 1 1 0 1 1 1 0 0 0 0 0 0 0 0 0
ve e e e e vm m m m m m m m m m m
1 1 0 1 1 1 1 0 0 0 0 0 0 0 0 0
12739
ganzzahliger Teil: 12739 | 1 6369 | 1 3184 | 0 1592 | 0 796 | 0 398 | 0 199 | 1 99 | 1 49 | 1 24 | 0 12 | 0 6 | 0 3 | 1 1 | 1 Nachkommateil: Gesamt: 0 11000111000011, Mantisse wäre: 1100011100 Exponent wäre: 14 Exponent umwandeln: 14 | 0 7 | 1 3 | 1 1 | 1 Exponent unbeschränkt positiv: 1110 Exponent: 1110, Vorzeichen: 0
vm m m m m m m m m m m ve e e e e
0 1 1 0 0 0 1 1 1 0 0 0 1 1 1 0
vm ve e e e e m m m m m m m m m m
0 0 1 1 1 0 1 1 0 0 0 1 1 1 0 0
ve e e e e vm m m m m m m m m m m
0 1 1 1 0 0 1 1 0 0 0 1 1 1 0 0
Zurückrechnen
Gegeben sind die Zahlen im 2. Format, m = 9 und e = 3:**0 0 1 0 1 1 1 1 1 1 0 0 0 0**
Beide Vorzeichen positiv
Mantisse: 1111100002
positiver Exponent: 1012 = 510
Zahl in normierter Gleitkommadarstellung: 0,111112 * 25 = 111112
Ergebnis: 31
**1 0 1 1 1 1 1 0 0 1 0 1 0 1**
Vorzeichen der Mantisse negativ, daher ist die Zahl negativ
Mantisse: 1100101012
positiver Exponent: 1112 = 710
Zahl in normierter Gleitkommadarstellung: -0,1100101012 * 27 = 1100101,012
Ergebnis: -101,25
**1 1 1 1 0 1 0 0 1 1 0 1 0 1**
beide Vorzeichen negativ, daher ist die Zahl negativ und der Exponent negativ
negative Mantisse: -1001101012
negativer Exponent, daher Zweierkomplement des Exponenten: 0102 = -210
Zahl in normierter Gleitkommadarstellung: -0,1001101012 * 2-2 = 0,001001101012
Ergebnis: -0.15087890625
(Vergleichen Sie das mit dem Ergebnis des Beispiels ganz oben!)
Zahlenbereich
Die Formel aus der Schulübung:
Eingesetzt für B = 2 (Binärsystem), m = 10 (von ganz oben) und e = 4 (von ganz oben):
Labels: POS1-1
# Eingestellt von Harald R. Haberstroh @ 22:20 0 Kommentare
Donnerstag, 10. März 2011
Lösungen zu "Übungsbeispiele zu Sequenzen, Schleifen und Funktionen in Python" (POS1: 1B)
Hier mögliche Lösungen zu der Aufgabe "Übungsbeispiele zu Sequenzen, Schleifen und Funktionen in Python (POS1: 1B)". Einige der Aufgaben enthalten Suchaufgaben. Die Funktionen dazu sind teilweise nicht "strukturiert" programmiert, das heißt, dass sie in diesen Fällen nicht nur ein return sondern mehrere Ausgänge haben. Um das zu verdeutlichen, beachten Sie folgendes Beispiel:
def isint(string): """prüft, ob der String eine ganze Zahl ist (Vorzeichen optional, nur Ziffern). Prüfe nur Ziffernbereich.""" if len(string) > 0: if string[0] == '+' or string[0] == '-': for c in string[1:]: if c < '0' or c > '9': return False else: for c in string: if c < '0' or c > '9': return False else: return False return True
Hier erfolgt ein return False aus den Schleifen über den String string, sobald ein Fehler gefunden wurde. Das vereinfacht den Algorithmus, widerspricht aber der strukturierten Programmierung, die bei Funkionen nur einen Ausgang erlaubt (bei Schleifen gilt das auch, die Schleife verlässt man nur durch die Schleifenbedingung, nicht durch break oder eben return). Beim Debuggen größerer Systeme ist es von Vorteil, wenn man sich darauf verlassen kann, dass jede Funktion nur einen Ausgang hat, denn man braucht dann nur diesen einen beobachten und nicht mehrere.
Bei obigem Beispiel müsste man while-Schleifen verwenden:
def isint(string): """prüft, ob der String eine ganze Zahl ist (Vorzeichen optional, nur Ziffern). Prüfe nur Ziffernbereich.""" ok = True if len(string) > 0: if string[0] == '+' or string[0] == '-': i = 1 while ok and i < len(string): if string[i] < '0' or string[i] > '9': ok = False i += 1 else: i = 0 while ok and i < len(string): if string[i] < '0' or string[i] > '9': ok = False i += 1 else: ok = False return ok
Diese Variante könne man noch "vereinfachen", weil sich die beiden Zweige mit oder ohne Vorzeichen nur im Startwert der Laufvariable i unterscheiden:
def isint(string): """prüft, ob der String eine ganze Zahl ist (Vorzeichen optional, nur Ziffern). Prüfe nur Ziffernbereich.""" ok = True if len(string) > 0: if string[0] == '+' or string[0] == '-': i = 1 else: i = 0 while ok and i < len(string): if string[i] < '0' or string[i] > '9': ok = False i += 1 else: ok = False return ok
Die "nicht strukturierte" Variante ist aber bei weitem schneller entwickelt und durch die automatischen Tests ist auch sichergestellt, dass sie funktioniert.
Die Tests verwenden assert(), um die Ergebnisse mit den erwarteten Ergebnissen zu vergleichen. assert() bricht das Programm auf der Stelle ab, wenn die Bedingung nicht erfüllt ist. Dadurch hat man die Möglichkeit, den Fehler einzugrenzen. Passt die Bedingung, so läuft das Programm einfach weiter.
""" author: Haberstroh, Harald matnr: d09666 file: sequenzenbeispiele.py desc: Beispiele einfacher Funktionen mit Sequenzen (vgl. Programmierblog) Einige Funktionen bauen auf den anderen auf.
Zu jeder Funktion (ausgenommen Hilfsfunktion) gibt es eine Testfunktion
die die jeweilige Funktion mit Testwerten prüft.
Die Funktion assert() prüft den Wahrheitswert des Parameters. Ist dieser
True, so läuft das Programm einfach weiter. Ist er jedoch False, wird
das Programm mit einer Fehlermeldung und Zeilennummer abgebrochen.
Man kann dadurch feststellen, welcher Test nicht funktioniert hat.date: 7.3.2011 class: Lehrer catnr: 33 """ #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def isint(string): """prüft, ob der String eine ganze Zahl ist (Vorzeichen optional, nur Ziffern). Prüfe nur Ziffernbereich.""" if len(string) > 0: if string[0] == '+' or string[0] == '-': for c in string[1:]: if c < '0' or c > '9': return False else: for c in string: if c < '0' or c > '9': return False else: return False return True
def test_isint(): assert(isint("") == False) assert(isint("a") == False) assert(isint("1a") == False) assert(isint("a1") == False) assert(isint("1+1") == False) assert(isint("1+") == False) assert(isint("1") == True) assert(isint("+1") == True) assert(isint("-1") == True) assert(isint("11212") == True) assert(isint("-11212") == True) assert(isint("+11212") == True) print("test_isint() ok")
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def isintb(string, basis): """prüft, ob der String eine ganze Zahl zur Basis basis ist (Vorzeichen optional, nur Ziffern). Baue String mit gültigen Zeichen zusammen und prüfe dann, ob jedes Zeichen in diesem String vorkommt.""" if basis > 1: gueltig = "" # "Liste" der gültigen Zeichen für geg. Basis if basis > 10: # Ziffern und Buchstaben (immer groß und klein) for z in range(10): gueltig += chr(z + ord('0')) for z in range(basis - 10): gueltig += chr(z + ord('a')) # Kleinbuchstabe gueltig += chr(z + ord('A')) # Großbuchstabe else: # nur Ziffern for z in range(basis): gueltig += chr(z + ord('0')) if len(string) > 0: if string[0] == '+' or string[0] == '-': # Vorzeichen for c in string[1:]: if c not in gueltig: return False else: for c in string: if c not in gueltig: return False else: return False else: return False return True # alles OK
def test_isintb(): assert(isintb("", 2) == False) assert(isintb("a", 2) == False) assert(isintb("1a", 2) == False) assert(isintb("a1", 2) == False) assert(isintb("1+1", 2) == False) assert(isintb("1+", 2) == False) assert(isintb("1", 2) == True) assert(isintb("+1", 2) == True) assert(isintb("-1", 2) == True) assert(isintb("11212", 2) == False) assert(isintb("-11212", 2) == False) assert(isintb("+11212", 2) == False) assert(isintb("11212", 3) == True) assert(isintb("-11212", 3) == True) assert(isintb("+11212", 3) == True) assert(isintb("aBCdeF", 16) == True) assert(isintb("-aBCdeF", 16) == True) assert(isintb("+aBCdeF", 16) == True) print("test_isintb() ok")
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
def sumdigits(zahl): """Berechnet die Ziffernsumme aus der gegebenen Zahl (int)""" sum = 0 while zahl != 0: sum += zahl % 10 # Rest ist immer Einerstelle zahl = zahl // 10 return sum
def test_sumdigits(): assert(sumdigits(0) == 0) assert(sumdigits(1) == 1) assert(sumdigits(7) == 7) assert(sumdigits(10) == 1) assert(sumdigits(11) == 2) assert(sumdigits(123) == 6) assert(sumdigits(1010) == 2) print("test_sumdigits() ok")
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def wert_der_ziffer(ziffer): """liefert den Wert der Ziffer ziffer (0..9, bzw. A, B, C, ...)""" if ord(ziffer) <= ord("9"): wert = ord(ziffer) - ord("0") else: wert = ord(ziffer) - ord("A") + 10 return wert
def horner(zahl, basis): """berechnet Dezimalzahl aus zahl (String) zur Basis basis. liefert Zahl. Hornerschema!""" dez = 0 for ziffer in zahl: dez *= basis dez += wert_der_ziffer(ziffer) return dez
def test_horner(): assert(horner("", 10) == 0) assert(horner("1", 10) == 1) assert(horner("12", 10) == 12) assert(horner("123", 10) == 123) assert(horner("1", 2) == 1) assert(horner("10", 2) == 2) assert(horner("11", 2) == 3) assert(horner("4", 16) == 4) assert(horner("A", 16) == 10) assert(horner("10", 16) == 16) print("test_horner() ok")
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def isipv4(string): """Prüft, ob der gegebene String eine IPv4-Adresse enthält. IPv4-Adressen sind 4 Zahlen zwischen 0 und 255, die durch einen Punkt getrennt sind. Beispiele: 127.0.0.1, 193.170.149.129, 81.200.64.185 Ungültige: 81.2010.64.185, 123.23.12, 127,0,0,1""" zahl = "" anzpunkte = 0 anzziffer = 0 for z in string: if '0' <= z <= '9': zahl += z anzziffer += 1 elif z == '.' and anzziffer > 0: # mindestens 1 Ziffer vor Zahl if not (0 <= horner(zahl, 10) <= 255): return False zahl = "" # neu beginnen anzziffer = 0 anzpunkte += 1 else: return False if anzpunkte == 3 and anzziffer > 0: # nach 3. Punkt eine Zahl! if not (0 <= horner(zahl, 10) <= 255): return False return True else: return False
def test_isipv4(): assert(isipv4("127.0.0.1")) assert(isipv4("193.170.149.129")) assert(isipv4("81.200.64.185")) assert(not isipv4("")) assert(not isipv4("81.2010.64.185")) assert(not isipv4("123.23.12")) assert(not isipv4("123.23.12.")) assert(not isipv4("123.23.12.3.3")) assert(not isipv4("123.23.12.3.")) assert(not isipv4("127,0,0,1")) print("test_isipv4() ok")
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def anz_zahlen(string): """ermittelt die Anzahl der ganzen Zahlen im String""" anzahl = 0 in_zahl = False for zeichen in string: if zeichen in "0123456789": if not in_zahl: anzahl += 1 in_zahl = True else: in_zahl = False return anzahl
def test_anz_zahlen(): string = "das ist eine Zahl 123 und noch eine 1 und noch eine 3213x23123" assert(4 == anz_zahlen(string)) assert(0 == anz_zahlen("keine")) assert(1 == anz_zahlen("eine Zahl 123")) assert(2 == anz_zahlen("zwei 23 und 324")) assert(3 == anz_zahlen("drei 23 34 22")) assert(4 == anz_zahlen("vier 234 234 234 45")) assert(5 == anz_zahlen("5 234 234 234 45")) print("test_anz_zahlen() ok")
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def sum_zahlen(string): """ermittelt die Summe der ganzen Zahlen im String. Eine Zahl ist eine ununterbrochene Folge von Ziffern. Beispiel: sum_zahlen("x 34 3 12k33 44 hallo 23") liefert 149""" summe = 0 zahl = "" for zeichen in string: if zeichen in "0123456789": zahl += zeichen else: summe += horner(zahl, 10) # umrechnen und dazuzählen zahl = "" # neu beginnen if len(zahl) > 0: # zuletzt war Zahl, daher dazurechnen summe += horner(zahl, 10) return summe
def test_sum_zahlen(): string = "das ist eine Zahl 123 und noch eine 1 und noch eine 3213x23123" assert(26460 == sum_zahlen(string)) assert(0 == sum_zahlen("keine")) assert(123 == sum_zahlen("eine Zahl 123")) assert(347 == sum_zahlen("zwei 23 und 324")) assert(79 == sum_zahlen("drei 23 34 22")) assert(747 == sum_zahlen("vier 234 234 234 45")) assert(752 == sum_zahlen("5 234 234 234 45")) print("test_sum_zahlen() ok")
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def iskonto(string): """Prüft, ob der String eine gültige Kontonummer enthält. Dabei gelten folgende Regeln: 1. genau 9 Ziffern (es dürfen Leerzeichen dazwischen sein 2. die letzte Ziffer ist eine Prüfziffer und es gilt Die Kontonummer ist genau 9 Stellen lang und ist dann richtig, wenn die folgendermaßen gebildete Summe auf Null endet: Ziffern mit ungeradem Index werden addiert(=Teilsumme1); Ziffern mit geradem Index werden verdoppelt und das jeweilige Produkt addiert, wenn es einstellig ist, andernfalls wird die Quersumme des Produkts addiert(=Teilsumme2); Summe= teilsumme1 + Teilsumme2 Beispiel: 123456782 1+ 3+ 5+ 7+ 2 = 18 Teilsumme1 22+ 42+ (1+2)+ (1+6) = 22 Teilsumme2 62=12 82=16 ------ 40 Summe mod 10= Null Beispiele für Kontonummern: 697199107 richtige Kontonummer 723016689 richtige Kontonummer 723016699 falsche Kontonummer """ # entferne alle Leerzeichen (sind ja erlaubt) kontonummer = "" for c in string: if '0' <= c <= '9': kontonummer += c elif c != ' ': return False # nur Ziffern und Leerzeichen erlaubt! if len(kontonummer) != 9: return False
summe = 0 # alles in einer Summe, aufteilen ist nicht nötig
for i in range(len(kontonummer)):
ziffer = ord(kontonummer[i]) - ord('0')
if (1 + i) % 2 == 1: # ungerade
summe += ziffer
else: # gerade
doppelt = ziffer * 2
if doppelt >= 10: # Zwei Ziffern
summe += doppelt % 10 # Einer
summe += doppelt // 10 # Zehner
else: # immer noch eine Ziffer
summe += doppelt
return summe % 10 == 0 # Summe muss durch 10 teilbar seindef test_iskonto(): assert(not iskonto("")) assert(not iskonto("a")) assert(not iskonto("69719a9107")) assert(not iskonto("69719917")) assert(not iskonto("723016699")) assert(iskonto("723016689")) assert(iskonto("697199107")) assert(iskonto("123456782")) assert(iskonto("12 345 6782")) print("test_iskonto() ok")
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def reverse_s(string): """liefert String in umgekehrter Reihenfolge zurück""" s = "" for c in string: s = c + s return s
def test_reverse_s(): assert("" == reverse_s("")) assert("a" == reverse_s("a")) assert("ba" == reverse_s("ab")) assert("abc" == reverse_s("cba")) print("test_reverse() ok")
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def toupper(string): """liefert String in Großbuchstaben zurück""" s = "" for c in string: if 'a' <= c <= 'z': s += chr(ord(c) - ord('a') + ord('A')) elif c == 'ä': s += 'Ä' elif c == 'ö': s += 'Ö' elif c == 'ü': s += 'Ü' else: s += c return s
def test_toupper(): assert("" == toupper("")) assert("A" == toupper("a")) assert("AB" == toupper("ab")) assert("ÄBC" == toupper("äbc")) assert("A" == toupper("a")) assert("AB" == toupper("Ab")) assert("ÄBC" == toupper("äBc")) print("test_toupper() ok")
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def tolower(string): """liefert String in Kleinbuchstaben zurück""" pass s = "" for c in string: if 'A' <= c <= 'Z': s += chr(ord(c) - ord('A') + ord('a')) elif c == 'Ä': s += 'ä' elif c == 'Ö': s += 'ö' elif c == 'Ü': s += 'ü' else: s += c return s
def test_tolower(): assert("" == tolower("")) assert("a" == tolower("A")) assert("ab" == tolower("AB")) assert("äbc" == tolower("ÄBC")) assert("a" == tolower("A")) assert("ab" == tolower("Ab")) assert("äbc" == tolower("äBc")) print("test_tolower() ok")
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def isupper(string): """prüft, ob String nur Großbuchstaben enthält""" for c in string: if 'a' <= c <= 'z' or c in "äöü": # ein Kleinbuchstabe return False return True
def test_isupper(): assert(isupper("")) assert(isupper("A")) assert(isupper("AEÄÖ")) assert(not isupper("a")) assert(not isupper("abcö")) assert(not isupper("AbC")) print("test_isupper() ok")
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def islower(string): """prüft, ob String nur Kleinbuchstaben enthält""" for c in string: if 'A' <= c <= 'Z' or c in "ÄÖÜ": # ein Großbuchstab return False return True
def test_islower(): assert(islower("")) assert(islower("a")) assert(islower("aeöä")) assert(not islower("A")) assert(not islower("ABCÖ")) assert(not islower("AbC")) print("test_islower() ok")
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def ispalindrom(string): """Prüft, ob der String ein Palindrom ist (von vorne und hinten gelesen gleich).""" for i in range(len(string)): if string[i] != string[-1 - i]: return False return True
def test_ispalindrom(): assert(ispalindrom("")) assert(ispalindrom("a")) assert(ispalindrom("aa")) assert(ispalindrom("aba")) assert(ispalindrom("abba")) assert(not ispalindrom("ab")) assert(not ispalindrom("abb")) assert(not ispalindrom("abab")) print("test_ispalindrom() ok")
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def ispalindrom_l(liste): """Prüft, ob die Liste von vorne und hinten gelesen gleich ist.""" return ispalindrom(liste) # sollte äquivalent sein!
def test_ispalindrom_l(): assert(ispalindrom_l([])) assert(ispalindrom_l([1])) assert(ispalindrom_l([1, 1])) assert(ispalindrom_l([1, 2, 1])) assert(ispalindrom_l([1, 2, 2, 1])) assert(not ispalindrom_l([1, 2])) assert(not ispalindrom_l([1, 2, 2])) assert(not ispalindrom_l([1, 2, 1, 2])) print("test_ispalindrom_l() ok")
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def reverse_l(liste): """liefert die Liste in umgekehrter Reihenfolge zurück""" l = [] for e in liste: l = [e] + l return l
def test_reverse_l(): assert([] == reverse_l([])) assert([1] == reverse_l([1])) assert([1, 2] == reverse_l([2, 1])) assert([1, 2, 3] == reverse_l([3, 2, 1])) print("test_reverse_l() ok")
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def sum(liste): """liefert die Summe aller Zahlen in der Liste""" summe = 0 for e in liste: summe += e return summe
def test_sum(): assert(0 == sum([])) assert(12 == sum([12])) assert(12 == sum([4, 8])) assert(12 == sum([4, 4, 4])) print("test_sum() ok")
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def mittelwert(liste): """liefert den Mittelwert (Durchschnitt) aller Zahlen in der Liste""" if len(liste) > 0: return sum(liste) / len(liste) else: return 0
def test_mittelwert():
assert(0 == mittelwert([]))
assert(1 == mittelwert([1]))
assert(1.5 == mittelwert([1, 2]))
assert(2 == mittelwert([2, 2, 2]))
assert(2 == mittelwert([1, 2, 3]))
print("test_mittelwert() ok")
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def rmdups(liste): """(ReMove DUPlicates) liefert Liste, aus der alle Vielfachen entfernt (hintereinander). Beispiele: [1, 2, 2, 2, 5, 2, 3, 2, 2, 23] -> [1, 2, 5, 2, 3, 2, 23] [99, 99, 23, 99, 99, 12, 2] -> [99, 23, 99, 12, 2] [] -> [] [1, 2, 4, 10] -> [1, 2, 4, 10]""" if len(liste) > 0: ret = [liste[0]] for e in liste: if ret[-1] != e: # letztes Element ungleich? ret.append(e) return ret else: return liste
def test_rmdups(): assert([1, 2, 5, 2, 3, 2, 23] == rmdups([1, 2, 2, 2, 5, 2, 3, 2, 2, 23])) assert([99, 23, 99, 12, 2] == rmdups([99, 99, 23, 99, 99, 12, 2])) assert([] == rmdups([])) assert([1, 2, 4, 10] == rmdups([1, 2, 4, 10])) print("test_rmdups() ok")
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def isin(item, liste): """ist item in liste enthalten?""" for e in liste: if item == e: return True return False
def rmalldups(liste): """(ReMove ALL DUPlicates) liefert Liste, aus der alle Vielfachen entfernt (müssen nicht hintereinander stehen). Beispiele: [1, 2, 2, 2, 5, 2, 3, 2, 2, 23] -> [1, 2, 5, 3, 23] [99, 99, 23, 99, 99, 12, 2] -> [99, 23, 12, 2] [] -> [] [1, 2, 4, 10] -> [1, 2, 4, 10]""" if len(liste) > 0: ret = [liste[0]] for e in liste:
if e not in ret: # schon vorhanden?
if not isin(e, ret):
ret.append(e)
return ret
else:
return listedef test_rmalldups(): assert([] == rmalldups([])) assert([1, 2, 5, 3, 23] == rmalldups([1, 2, 2, 2, 5, 2, 3, 2, 2, 23])) assert([99, 23, 12, 2] == rmalldups([99, 99, 23, 99, 99, 12, 2])) assert([1, 2, 4, 10] == rmalldups([1, 2, 4, 10])) print("test_rmalldups() ok")
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def binsearch(liste, such): """liefert den Index von such in der sortierten Liste liste oder -1, wenn such in liste nicht vorkommt. Es ist die binäre Suche anzuwenden! """ first = 0 last = len(liste) - 1 mid = (last - first) // 2 + first #print(first, mid, last) while len(liste) > 0 and first <= last: if such < liste[mid]: last = mid - 1 elif such > liste[mid]: first = mid + 1 else: return mid #index found mid = (last - first) // 2 + first #print(first, mid, last) return -1 # not found
def test_binsearch(): """static tests""" assert(binsearch([], 1) == -1) assert(binsearch([1], 2) == -1) assert(binsearch([1], 0) == -1) assert(binsearch([1], 1) == 0) assert(binsearch([1,3], 0) == -1) assert(binsearch([1,3], 2) == -1) assert(binsearch([1,3], 1) == 0) assert(binsearch([1,3], 3) == 1) assert(binsearch([1,3], 4) == -1) assert(binsearch([1,3,5], 2) == -1) assert(binsearch([1,3,5], 4) == -1) assert(binsearch([1,3,5], 1) == 0) assert(binsearch([1,3,5], 3) == 1) assert(binsearch([1,3,5], 5) == 2) assert(binsearch([1,3,5], 6) == -1) assert(binsearch([1,3,5,7], 0) == -1) assert(binsearch([1,3,5,7], 1) == 0) assert(binsearch([1,3,5,7], 3) == 1) assert(binsearch([1,3,5,7], 5) == 2) assert(binsearch([1,3,5,7], 7) == 3) assert(binsearch([1,3,5,7], 9) == -1) assert(binsearch([1,3,5,7], 2) == -1) assert(binsearch([1,3,5,7], 4) == -1) assert(binsearch([1,3,5,7], 6) == -1) import random for i in range(25): liste = [random.randint(0, 100) for i in range(100)] liste.sort() num = random.randint(0, 100) if num in liste: if binsearch(liste, num) < 0: print(liste) print("%d should be found in list" % num) assert(binsearch(liste, num) >= 0) else: if binsearch(liste, num) >= 0: print(liste) print("%d should not be found in list" % num) assert(binsearch(liste, num) < 0) print("test_binsearch() ok")
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def sumteilbar(liste, teiler): """Berechnet die Summe aller durch teiler teilbaren Zahlen der Liste""" summe = 0 for e in liste: if e % teiler == 0: summe += e return summe
def test_sumteilbar(): assert(0 == sumteilbar([], 2)) assert(0 == sumteilbar([1], 2)) assert(0 == sumteilbar([1, 3], 2)) assert(0 == sumteilbar([1, 3, 23], 2)) assert(2 == sumteilbar([2], 2)) assert(2 == sumteilbar([1, 2], 2)) assert(2 == sumteilbar([1, 2, 23], 2)) assert(32 == sumteilbar([1, 8, 24], 2)) assert(27 == sumteilbar([3, 8, 24], 3)) print("test_sumteilbar() ok")
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def issorted(liste): """Prüft, ob die Liste sortiert ist, d.h. ob e1 <= e2 <= e3 <= ... <= en e1, e2, ... en sind die n Elemente der Liste mit Länge n""" for i in range(len(liste) - 1): if liste[i] > liste[i + 1]: return False return True
def test_issorted(): assert(issorted([])) assert(issorted([1])) assert(issorted([1, 1])) assert(issorted([1, 3, 3, 4])) assert(not issorted([1, 0])) assert(not issorted([1, 2, 1])) print("test_issorted() ok")
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def printlxl(liste1, liste2): """gibt eine Multiplikationstabelle der beiden Listen aus. Zum Beispiel: a = [1, 2, 4, 5] b = [3, 2, 2] printlxl(a, b) gibt dann folgendes aus: 3 2 2 6 4 4 12 8 8 15 10 10 Die erste Liste bestimmt die Anzahl der Zeilen, die zweite die Anzahl der Spalten. Es wird immer ein Element der ersten Liste mit einem der zweiten Liste multipliziert. """ erg = lxl(liste1, liste2) for zeile in erg: for spalte in zeile: print("%4d" % spalte, end = "") print()
def test_printlxl(): a = [1, 2, 4, 5] b = [3, 2, 2] printlxl(a, b) print("test_printlxl() ok")
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+---- def lxl(liste1, liste2): """liefert eine Multiplikationstabelle der beiden Listen (Liste von Listen). Zum Beispiel: a = [1, 2, 4, 5] b = [3, 2, 2] lxl(a, b) liefert folgende Liste zurück: [[3, 2, 2], [6, 4, 4], [12, 8, 8], [15, 10, 10]] übersichtlich formatiert: [[3, 2, 2], [6, 4, 4], [12, 8, 8], [15, 10, 10]] Die erste Liste bestimmt die Anzahl der "Zeilen", die zweite die Anzahl der "Spalten". Es wird immer ein Element der ersten Liste mit einem der zweiten Liste multipliziert. """ erg = [] if len(liste2) > 0: for a in liste1: zeile = [] for b in liste2: zeile.append(a * b) erg.append(zeile) return erg
def test_1x1(): a = [1, 2, 4, 5] b = [3, 2, 2] assert([[3, 2, 2], [6, 4, 4], [12, 8, 8], [15, 10, 10]] == lxl(a, b)) assert([] == lxl([], [])) assert([] == lxl([], [1, 2])) assert([] == lxl([1, 2], [])) print("test_1x1() ok")
#---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
Testaufrufe:
test_isint() test_isintb() test_sumdigits() test_horner() test_isipv4() test_anz_zahlen() test_sum_zahlen() test_iskonto() test_reverse_s() test_toupper() test_tolower() test_isupper() test_islower() test_ispalindrom() test_ispalindrom_l() test_reverse_l() test_sum() test_mittelwert() test_rmdups() test_rmalldups() test_binsearch() test_sumteilbar() test_issorted() test_printlxl() test_1x1()
Die Funktionen isupper() und islower() sind eigentlich nicht korrekt, denn liefert z.B. isupper("A4C") True. Man müsste also eher schreiben:
def isupper(string): """prüft, ob String nur Großbuchstaben enthält""" for c in string: if not ('A' <= c <= 'Z' or c in "ÄÖÜ"): return False return True
Labels: Lösung, POS1-1, Python
# Eingestellt von Harald R. Haberstroh @ 08:37 0 Kommentare
Sonntag, 6. März 2011
Übungsbeispiele zu Sequenzen, Schleifen und Funktionen in Python (POS1: 1B)
Hier finden Sie eine Reihe von Aufgabenstellungen als Übung zur nächsten praktischen Arbeit.
Gegeben sind minimale Funktionsrümpfe mit der Aufgabenstellung als DocString.
Die Funktionen sind ohne Standardmethoden bzw. Funktionen zu implementieren (ausgenommen die Funktion len()). Sollte es eine Standardfunktion zur Lösung der Aufgabe geben, verwenden Sie diese, um das Ergebnis zu prüfen. Bereiche ([von:bis]) dürfen verwendet werden, sofern sie benötigt werden.
def isint(string) """prüft, ob der String eine ganze Zahl ist (Vorzeichen optional, nur Ziffern)""" pass
def isintb(string, basis) """prüft, ob der String eine ganze Zahl zur Basis basis ist (Vorzeichen optional, nur Ziffern)""" pass
def isnum(string) """prüft, ob der String eine Zahl ist (Vorzeichen optional, Ziffern und Komma)""" pass
def horner(zahl, basis): """berechnet Dezimalzahl aus zahl (String) zur Basis basis. liefert Zahl.""" pass
def sumdigits(zahl): """Berechnet die Ziffernsumme aus der gegebenen Zahl (int)""" pass
def sumdigits_s(string): """Berechnet die Ziffernsumme aus der gegebenen Zahl (str), wenn es überhaupt eine Zahl ist. Liefert -1, wenn keine gültige Zahl""" pass
def isipv4(string): """Prüft, ob der gegebene String eine IPv4-Adresse enthält. IPv4-Adressen sind 4 Zahlen zwischen 0 und 255, die durch einen Punkt getrennt sind. Beispiele: 127.0.0.1, 193.170.149.129, 81.200.64.185 Ungültige: 81.2010.64.185, 123.23.12, 127,0,0,1""" pass
def anz_vokale(string): """Zähle die Selbstlaute im String und liefere Anzahl zurück""" pass
def anz_zahlen(string): """ermittelt die Anzahl der ganzen Zahlen im String. Eine Zahl ist eine ununterbrochene Folge von Ziffern. Beispiel: anz_zahlen("x 34 3 12k33 44 hallo 23") liefert 6""" pass
def sum_zahlen(string): """ermittelt die Summe der ganzen Zahlen im String. Eine Zahl ist eine ununterbrochene Folge von Ziffern. Beispiel: anz_zahlen("x 34 3 12k33 44 hallo 23") liefert 149""" pass
def iskonto(string): """Prüft, ob der String eine gültige Kontonummer enthält. Dabei gelten folgende Regeln: 1. genau 9 Ziffern (es dürfen Leerzeichen dazwischen sein 2. die letzte Ziffer ist eine Prüfziffer und es gilt Die Kontonummer ist genau 9 Stellen lang und ist dann richtig, wenn die folgendermaßen gebildete Summe auf Null endet: Ziffern mit ungeradem Index werden addiert(=Teilsumme1); Ziffern mit geradem Index werden verdoppelt und das jeweilige Produkt addiert, wenn es einstellig ist, andernfalls wird die Quersumme des Produkts addiert(=Teilsumme2); Summe= teilsumme1 + Teilsumme2 Beispiel: 123456782 1+ 3+ 5+ 7+ 2 = 18 Teilsumme1 22+ 42+ (1+2)+ (1+6) = 22 Teilsumme2 62=12 82=16 ------ 40 Summe mod 10= Null Beispiele für Kontonummern: 697199107 richtige Kontonummer 723016699 falsche Kontonummer """ pass
def reverse_s(string): """liefert String in umgekehrter Reihenfolge zurück""" pass
def toupper(string): """liefert String in Großbuchstaben zurück""" pass
def tolower(string): """liefert String in Kleinbuchstaben zurück""" pass
def isupper(string): """prüft, ob String nur Großbuchstaben enthält""" pass
def islower(string): """prüft, ob String nur Kleinbuchstaben enthält""" pass
def ispalindrom(string): """Prüft, ob der String ein Palindrom ist (von vorne und hinten gelesen gleich).""" pass
def ispalindrom_l(liste): """Prüft, ob die Liste von vorne und hinten gelesen gleich ist.""" pass
def reverse_l(liste): """liefert die Liste in umgekehrter Reihenfolge zurück""" pass
def sum(liste): """liefert die Summe aller Zahlen in der Liste""" pass
def mittelwert(liste): """liefert den Mittelwert (Durchschnitt) aller Zahlen in der Liste""" pass
def rmdups(liste): """(ReMove DUPlicates) liefert Liste, aus der alle Vielfachen entfernt (hintereinander). Beispiele: [1, 2, 2, 2, 5, 2, 3, 2, 2, 23] -> [1, 2, 5, 2, 3, 2, 23] [99, 99, 23, 99, 99, 12, 2] -> [99, 23, 99, 12, 2] [] -> [] [1, 2, 4, 10] -> [1, 2, 4, 10]""" pass
def rmalldups(liste): """(ReMove ALL DUPlicates) liefert Liste, aus der alle Vielfachen entfernt (müssen nicht hintereinander stehen). Beispiele: [1, 2, 2, 2, 5, 2, 3, 2, 2, 23] -> [1, 2, 5, 3, 23] [99, 99, 23, 99, 99, 12, 2] -> [99, 23, 12, 2] [] -> [] [1, 2, 4, 10] -> [1, 2, 4, 10]""" pass
def binsearch(liste, such): """liefert den Index von such in der sortierten Liste liste oder -1, wenn such in liste nicht vorkommt. Es ist die binäre Suche anzuwenden! """ pass
def sumdigits(zahl): """Berechnet die Ziffernsumme aus der gegebenen Zahl (int)""" pass
def sumteilbar(liste, teiler): """Berechnet die Summe aller durch teiler teilbaren Zahlen der Liste""" pass
def issorted(liste): """Prüft, ob die Liste sortiert ist, d.h. ob e1 <= e2 <= e3 <= ... <= en e1, e2, ... en sind die n Elemente der Liste mit Länge n""" pass
def printlxl(liste1, liste2): """gibt eine Multiplikationstabelle der beiden Listen aus. Zum Beispiel: a = [1, 2, 4, 5] b = [3, 2, 2] printlxl(a, b) gibt dann folgendes aus: 3 2 2 6 4 4 12 8 8 15 10 10 Die erste Liste bestimmt die Anzahl der Zeilen, die zweite die Anzahl der Spalten. Es wird immer ein Element der ersten Liste mit einem der zweiten Liste multipliziert. """ pass
def lxl(liste1, liste2): """liefert eine Multiplikationstabelle der beiden Listen (Liste von Listen). Zum Beispiel: a = [1, 2, 4, 5] b = [3, 2, 2] lxl(a, b) liefert folgende Liste zurück: [[3, 2, 2], [6, 4, 4], [12, 8, 8], [15, 10, 10]] übersichtlich formatiert: [[3, 2, 2], [6, 4, 4], [12, 8, 8], [15, 10, 10]] Die erste Liste bestimmt die Anzahl der "Zeilen", die zweite die Anzahl der "Spalten". Es wird immer ein Element der ersten Liste mit einem der zweiten Liste multipliziert. """ pass
Schreiben Sie zu den Funktionen jeweils passende Testprogramme.
Labels: Aufgabe, POS1-1, Python
# Eingestellt von Harald R. Haberstroh @ 21:34 0 Kommentare
Freitag, 14. Januar 2011
Ganze Zahlen zählen (Schleife, Sequenzen, Funktionen POS1: 1BHIF)
Schreiben Sie ein Programm anzzahlen.py, welches eine Zeile einliest und in dieser Zeile zähle, wieviele ganze Zahlen vorkommen. Jedes Zeichen, das keine Ziffer ist, gilt als nicht zu einer Zahl gehörend.
Beispiel:
Eingabe:
das ist eine Zahl 123 und noch eine 1 und noch zwei 3213x23123
Ausgabe:
4 Zahlen gefunden.
Das Programm soll richtige Sätze ausgeben, also "Keine Zahlen gefunden.", wenn in der Eingabe keine Zahlen sind oder "Eine Zahl gefunden.", wenn eine Zahl in der Eingabe war. Ab 4 soll dann die Zahl ausgegeben werden, z.B. "6 Zahlen gefunden."
Mögliche Lösung:
""" author: Haberstroh, Harald matnr: d09666 file: anzzahlen.py desc: Zähle ganze Zahlen Beispiel: das ist eine Zahl 123 und noch eine 1 und noch zwei 3213x23123 Ausgabe: 4 Zahlen gefunden date: 14.1.2011 class: Lehrer catnr: 33 """ #---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
def anz_zahlen(string): """ermittelt die Anzahl der ganzen Zahlen im String""" anzahl = 0 in_zahl = False for zeichen in string: if zeichen in "0123456789": if not in_zahl: anzahl += 1 in_zahl = True else: in_zahl = False return anzahl
def ausgabe(anzahl): """gibt deutschen Satz aus mit Anzahl""" if anzahl == 0: print("Keine Zahl gefunden.") elif anzahl == 1: print("Eine Zahl gefunden.") elif anzahl == 2: print("Zwei Zahlen gefunden.") elif anzahl == 3: print("Drei Zahlen gefunden.") else: print(anzahl, "Zahlen gefunden.")
def main(): """EVA Eingave Verarbeitung Ausgabe - das Hauptprogramm""" string = input("> ") anzahl = anz_zahlen(string) ausgabe(anzahl)
def test(): """Testen von anz_zahlen() und ausgabe()""" string = "das ist eine Zahl 123 und noch eine 1 und noch eine 3213x23123" anzahl = anz_zahlen(string) ausgabe(anzahl) ausgabe(anz_zahlen("keine")) ausgabe(anz_zahlen("eine Zahl 123")) ausgabe(anz_zahlen("zwei 23 und 324")) ausgabe(anz_zahlen("drei 23 34 22")) ausgabe(anz_zahlen("vier 234 234 234 45")) ausgabe(anz_zahlen("5 234 234 234 45"))
if name == 'main': main()
test()
Beachten Sie, dass ich hier eine eigene Funktion test() gemacht habe, um viele Testfälle immer wieder leicht probieren zu können. Statt main() muss dann nur test() aufgerufen werden.
Das Programm wäre auch ohne die Funktion test() fertig und korrekt. test() half nur bei der Entwicklung bei der Fehlersuche.
Labels: Aufgabe, Lösung, POS1-1, Python
# Eingestellt von Harald R. Haberstroh @ 12:32 0 Kommentare
Freitag, 3. Dezember 2010
Wurzelberechnung (POS1: 1BHIF)
Man kann die Wurzel einer Zahl berechnen mit folgender Formel
xn = (xn-1 + a / xn-1) / 2
Man beginnt damit, dass a und x0 gleich der Zahl, aus der man die Wurzel ziehen will, setzt und x1 berechnet. Dann berechnet man x2 usw. bis sich die beiden letzten Werte nur mehr gering unterscheiden (z.B. die Differenz kleiner 0,0000001 ist).
Schreiben Sie eine Funktion wurzel(zahl, genauigkeit), welche nach obiger Methode die Wurzel berechnet.
Erstellen Sie ein Programm wurzel.py, welche eine Tabelle der Wurzeln der Zahlen 1 bis 20 bei den Genauigkeiten 0.01, 0.0001 sowie 0.0000001 ausgibt:
1: 1.0000000 1.0000000 1.0000000 2: 1.4142157 1.4142136 1.4142136 3: 1.7320508 1.7320508 1.7320508 4: 2.0000001 2.0000000 2.0000000 5: 2.2360689 2.2360680 2.2360680 6: 2.4494944 2.4494897 2.4494897 7: 2.6457670 2.6457513 2.6457513 8: 2.8284271 2.8284271 2.8284271 9: 3.0000000 3.0000000 3.0000000 10: 3.1622777 3.1622777 3.1622777 11: 3.3166248 3.3166248 3.3166248 12: 3.4641017 3.4641016 3.4641016 13: 3.6055514 3.6055513 3.6055513 14: 3.7416576 3.7416574 3.7416574 15: 3.8729837 3.8729833 3.8729833 16: 4.0000006 4.0000000 4.0000000 17: 4.1231067 4.1231056 4.1231056 18: 4.2426425 4.2426407 4.2426407 19: 4.3589018 4.3588989 4.3588989 20: 4.4721402 4.4721360 4.4721360
Labels: Aufgabe, POS1-1, Python
# Eingestellt von Harald R. Haberstroh @ 12:27 0 Kommentare
Musterlösung zu Übungsbeispiele für Python vom 1.12.2010 (POS1: 1BHIF)
Prüfen, ob durch die Angabe dreier Längen ein Dreieck gegeben ist.
Zwei Seiten müssen immer länger als die dritte sein. Man muss dies für alle Möglichkeiten prüfen, denn z.B.
a = 3, b = 4, c = 1
Da stimmt zwar a + b > c (7 > 1) und b + c > a (4 > 3), jedoch nicht a + c > b (4 == 4)!
Bei der Lösung wird eine Schleife verwendet.
def ist_dreieck(a, b, c): """liefert True, wenn durch a, b und c ein gültiges Dreieck definiert ist""" i = 3 while i > 0: if a + b <= c: return False # kein Dreieck a, b, c = b, c, a i = i - 1 return True
Man könnte das Problem natürlich auch durch logische Verknüpfung der Prüfungen lösen:
def ist_dreieck(a, b, c): """liefert True, wenn durch a, b und c ein gültiges Dreieck definiert ist""" if a + b > c and b + c > a and c + a > b: ret = True else: ret = False return ret
Oder gleich so:
def ist_dreieck(a, b, c): """liefert True, wenn durch a, b und c ein gültiges Dreieck definiert ist""" return a + b > c and b + c > a and c + a > b
Bei der zweiten Aufgabe soll geprüft werden, ob durch zwei Seiten und einem Winkel ein Quadrat gegeben ist. Die beiden Seiten müssen gleich lang sein (und größer 0) und der Winkel 90°:
def ist_quadrat(a, b, w): """liefert True, wenn durch a und b sowie dem Winkel w ein Quadrat definiert ist""" quadrat = False if a > 0: if a == b: if w == 90: quadrat = True # else entfällt, da die Variable quadrat schon mit False vorbelegt ist. return quadrat
Oder wieder kürzer mit logischer Verknüpfung:
def ist_quadrat(a, b, w): """liefert True, wenn durch a und b sowie dem Winkel w ein Quadrat definiert ist""" return a == b and w == 90 and a > 0
Die Schaltjahrprüfung könnte so erfolgen:
def ist_schaltjahr(jahr): """liefert True, wenn das gegebene Jahr ein Schaltjahr ist. Seit Ende 1582 gilt der Gregorianische Kalender, bei dem folgende Regel für die Schaltjahrbestimmung anzuwenden sind: In allen Jahren, deren Jahreszahl durch vier teilbar ist, ist der 29. Februar ein Schalttag und damit ist dieses Jahr ein Schaltjahr. Eine Ausnahme bilden allerdings die vollen Jahrhundertjahre 1700, 1800, 1900 usw., auch Säkularjahre genannt. Hiervon erhalten nur diejenigen einen Schalttag, deren Jahreszahl durch 400 teilbar ist. Jedes vierte Säkularjahr ist somit ein Schaltjahr. Für alle Jahre <= 1582 liefert die Funktion False, weil da das Schaltjahr nicht definiert ist, sonst gilt obige Regel.""" if jahr <= 1582: schaltjahr = False elif jahr % 400 == 0: schaltjahr = True elif jahr % 100 == 0: schaltjahr = False elif jahr % 4 == 0: schaltjahr = True else: schaltjahr = False return schaltjahr
Jahre bis 1582 können keine Schaltjahre sein, da der Gregorianische Kalender erst im Jahr 1582 definiert wurde. Zum Test der Schaltjahrprüfung noch ein paar Worte, aber zunächst die Testfunktion, die ein paar Jahreszahlen prüft, von denen man weiß, dass sie kein Schaltjahr sind sowie Zahlen, bei denen bekannt ist, dass sie Schaltjahre sind:
def test_ist_schaltjahr(): for jahr in (1000, 1580, 1581, 1582, 1900, 1999, 2003): assert not ist_schaltjahr(jahr) for jahr in (1996, 2000, 2004): assert ist_schaltjahr(jahr) print("ist_schaltjahr ok")
Die Anweisung assert ist für Programmierer und dient zum Prüfen der Bedingung, die gleich dahinter folgt, gedacht. Zum Beispiel:
assert 3 < 4
Die Bedingung ist wahr, daher läuft das Programm weiter. Ist die Bedingung hingegen falsch, so wird das Programm mit einer Fehlermeldung abgebrochen:
assert 3 > 4 Traceback (most recent call last): File "<pyshell#0>", line 1, in assert 3 > 4 AssertionError </pyshell#0>
Zusätzlich kann ein Text als Fehlermeldung angegeben werden:
assert 3 > 4, "3 ist nicht größer als 4" Traceback (most recent call last): File "<pyshell#1>", line 1, in assert 3 > 4, "3 ist nicht größer als 4" AssertionError: 3 ist nicht größer als 4 </pyshell#1>
Angewendet auf obige Testfunktion bedeutet das, dass immer, wenn assert not ist_schaltjahr(jahr) die Funktion ist_schaltjahr(jahr) den Wert
<codeclass="prettyprint">False leifern muss und wenn assert ist_schaltjahr(jahr) steht, True geleifert werden muss, damit das Programm nicht abgebrochen wird. Der nächste Punkt ist die for jahr in (1000, 1580, 1581, 1582, 1900, 1999, 2003):-Zeile. Die Variable jahr bekommt der Reihe nach die Werte 1000, 1580, 1581, 1582, 1900, 1999, 2003 und der eingerückte Code-Block (die eine Zeile) wird ausgeführt. Das ist die for-Schleife, welche im Buch im Kapitel 7 auch erklärt wird. Die Funktion test_ist_schaltjahr() prüft also zunächst ein paar Jahre, die kein Schaltjahr sind und ein paar Schaltjahre. Die Fibonaccizahlen können wie folgt ermittelt werden: </codeclass="prettyprint">
def fib(n): """liefert die Fibonaccizahl zu n. Die Zahlen sind wie definiert: fib(0) -> 0 fib(1) -> 1 fib(2) -> 1 fib(3) -> 2 fib(4) -> 3 fib(5) -> 5 fib(6) -> 8 ... fib(10) -> 55 ... fib(15) -> 610""" f = 0 a = 0 b = 1 i = 0 while i < n: f = a + b b, a = a, f i += 1 return f
Für n = 0 und n = 1 sind die (Anfangs-)Werte vordefiniert. fib(0) = 0 und fib(1) = 1. Danach gilt die Regel, dass die n. Fibonaccizahl die Summe der beiden Vorgänger ist, also fib(n - 1) + fib(n - 2) (Siehe dazu auch Wikipedia: Fibonacci-Folge). Die Variable f hat immer den Wert der aktuellen Fibonaccizahl und ist daher mit 0 initialisiert. Die Variable a und b haben immer den Wert der beiden Vorgänger. Sie können das leicht sehen, wenn Sie print(...)-Anweisungen einfügen und sich dadurch den Ablauf der Berechnung anzeigen lassen:
def fib(n): """liefert die Fibonaccizahl zu n.""" f = 0 a = 0 b = 1 i = 0 while i < n: f = a + b print(i, ": f =", f, "a =", a, "b =", b) # Testausgabe b, a = a, f i += 1 return f
print(fib(10))
..gibt dann folgendes aus:
0 : f = 1 a = 0 b = 1 1 : f = 1 a = 1 b = 0 2 : f = 2 a = 1 b = 1 3 : f = 3 a = 2 b = 1 4 : f = 5 a = 3 b = 2 5 : f = 8 a = 5 b = 3 6 : f = 13 a = 8 b = 5 7 : f = 21 a = 13 b = 8 8 : f = 34 a = 21 b = 13 9 : f = 55 a = 34 b = 21 55
Die Ausgabe einer Tabelle mithilfe der Funktion fib() ist einfach (oder doch etwas kompliziert, weil die eckigen Klammern dazukommen):
def fibtab(n): """erzeugt eine Tabelle der Fibonaccizahlen bis inclusive n. z.B. gibt fibtab(10) folgendes aus: [0, 1, 1, 2, 3, 5, 8] oder fibtab(100): [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] Hinweis: verwenden Sie als Zeilenumbruch ", " beim print, also print(wert, end=', ') außer natürlich beim letzten Wert, hier ist "]" gefordert. """ i = 0 print("[", end = "") f = fib(i) while f <= n: print(f, end = "") i += 1 f = fib(i) if f > n: print("]") else: print(", ", end = "")
Wir müssen sicherstellen, dass zunächst "[" ohne Zeilenumbruch ausgegeben wird. Die Funktion print(...) hat einen optionalen Parameter end, der angibt, was zum Schluss ausgegeben werden soll. Standardmäßig ist das "\n", was einen Zeilenumbruch bewirkt. Setzt man den Wert end = "", so wird ein Leerstring, also nichts, ausgegeben. In der Schleife muss man noch prüfen, ob man das Ende erreicht hat und in diesem Fall "]" (mit Zeilenumbruch) ausgibt. Im Normalfall wird ein Komma ohne Zeilenumbruch ausgegeben (letzte Zeile). Beachten Sie, dass der Parameter n hier die Grenze der Fibonaccizahl angibt und nicht die wievielte (wie bei fib(n)). Die Lösung zum Beispiel, die Summe der Vielfachen von 3 und 5 kleiner als ein Maximum:
def sum_3_5(max): """ bilde Summe der Vielfachen von 3 und 5 kleiner als max. Beispielsweise liefert sum_3_5(10) 23, weil die Vielfachen von 3 < 10 sind 3 + 6 + 9 = 18 die Vielfachen von 5 < 10 sind 5 18 + 5 = 23 sum_3_5(20) liefert 78, weil 3+ 6+9+ 12+15+18=63 5+ 10+ =15 (15 ist in obiger Liste schon enthalten!) sum_3_5(25) liefert 143, weil 3+ 6+9+ 12+ 18+ 21+24=93 (Vielfache von 5 stehen darunter) 5+ 10+ 15+ 20 =50 sum_3_5(100) liefert 2318 (ohne Beweis) """ summe = 0 i = 0 while i < max: if i % 5 == 0: summe += i elif i % 3 == 0: summe += i i += 1 return summe
Die Laufvariable i wird immer dann zur summe dazugezählt, wenn sie durch 5 teilbar ist oder wenn sie durch 3 teilbar ist. Der Operator % berechnet den Rest der Division. Ist der Rest 0, so ist die erste durch die zweite Zahl teilbar. Das Beispiel zum finden des nächstkleineren bzw. gleichen Quadrats kann so mit einer Probiermethode gelöst werden:
def minquad(zahl): """finde die nächstkleinere oder gleichgroße ganze Zahl, die eine Quadratzahl ist. Beispiele: minquad(16) -> 16 (weil 4 * 4 = 16 <= 16) minquad(24) -> 24 (weil 4 * 4 = 16 <= 14) minquad(25) -> 25 (weil 5 * 5 = 25 <= 25) minquad(26) -> 25 (weil 5 * 5 = 25 <= 26) """ i = 0 mq = 0 while i ** 2 <= zahl: mq = i ** 2 i += 1 return mq
i ** 2 bedeutet i2. Man könnte natürlich auch i * i schreiben. Diese Funktion prüft einfach sukzessive alle Quadrate, bis eines gefunden wurde, das größer als die gegebene Zahl ist. Der Wert davor (die Variable mq) ist natürlich das Ergebnis, weil das der größte Wert war, für den die Bedingung gilt. Es geht natürlich schneller und einfacher, wenn man sich eine Formel überlegt:
from math import sqrt from math import floor def minquad(zahl): """finde die nächstkleinere oder gleichgroße ganze Zahl, die eine Quadratzahl ist. Beispiele: minquad(16) -> 16 (weil 4 * 4 = 16 <= 16) minquad(24) -> 16 (weil 4 * 4 = 16 <= 24) minquad(25) -> 25 (weil 5 * 5 = 25 <= 25) minquad(26) -> 25 (weil 5 * 5 = 25 <= 26) """ return int(floor(sqrt(zahl))) ** 2
Die Funktion floor(x) liefert die nächstkleinere ganze Zahl zu x (bei positiven Zahlen schneidet dir Funktion die Nachkommastellen der übergebenen Zahl ab). Z.B:
from math import floor floor(3.14) 3 floor(3) 3 floor(-3.14) -4
Wenn man die nächstkleinere ganze Zahl der Wurzel quadriert, hat man das gewünschte Ergebnis. Die Turtle-Funktion zum Dreieckzeichnen könnte wie folgt aussehen und braucht nicht weiter erklärt werden:
def dreieck(a, w): """zeichnet ein gleichseitiges Dreieck der Seitenlänge a, gedreht um den Winkel w. w = 0 bedeutet, dass die eine Seite horizional ist. w = 90 bedeutet, dass das Dreieck nach LINKS um 90° gedreht ist, d.h. eine Seite ist vertikal. Das Dreieck soll rechts neben des angegebenen Punktes gezeichnet werden. """ # nehme an Turtle sieht nach oben (wie auch beim Starten) right(90 - w) pendown() for i in range(3): forward(a) left(120) penup() left(90 - w)
Um ein Dreieck an eine bestimmte Position zu setzen, kann zusätzlich die Funktion setpos(x, y), welche die Turtle an die Postion x,y setzt, verwendet werden:
def dreieck_an_pos(a, w, x, y): """zeichnet ein Dreieck mit Hilfe der Funktion dreieck(a, w) an der Position x, y.""" penup() setpos(x, y) dreieck(a, w)
Abgesehen von den Turtle-Funktionen können Sie die Funktionen direkt auf der Website http://codepad.org testen. Dort können Sie auch andere Programmiersprachen probieren. Die Python-Version ist leider nicht aktuell, daher könnte es sein, dass einiges doch nicht direkt so funktioniert. Diese einfachen Beispiele funktionieren aber.
Hier ist zu minquad(zahl) zu sehen:
Labels: Lösung, POS1-1, Python
# Eingestellt von Harald R. Haberstroh @ 10:30 0 Kommentare
Mittwoch, 1. Dezember 2010
Übungsbeispiele für Python (POS1: 1BHIF)
Vervollständigen Sie die folgenden Funktionsdefinitionen und schreiben Sie passende Testaufrufe.
def ist_dreieck(a, b, c): """liefert True, wenn durch a, b und c ein gültiges Dreieck definiert ist""" return True
def ist_quadrat(a, b, w): """liefert True, wenn durch a und b sowie dem Winkel w ein Quadrat definiert ist""" return True
def ist_schaltjahr(jahr): """liefert True, wenn das gegebene Jahr ein Schaltjahr ist. Seit Ende 1582 gilt der Gregorianische Kalender, bei dem folgende Regel für die Schaltjahrbestimmung anzuwenden sind: In allen Jahren, deren Jahreszahl durch vier teilbar ist, ist der 29. Februar ein Schalttag und damit ist dieses Jahr ein Schaltjahr. Eine Ausnahme bilden allerdings die vollen Jahrhundertjahre 1700, 1800, 1900 usw., auch Säkularjahre genannt. Hiervon erhalten nur diejenigen einen Schalttag, deren Jahreszahl durch 400 teilbar ist. Jedes vierte Säkularjahr ist somit ein Schaltjahr. Für alle Jahre <= 1582 liefert die Funktion False, weil da das Schaltjahr nicht definiert ist, sonst gilt obige Regel.""" return False
def fib(n): """liefert die Fibonaccizahl zu n. Die Zahlen sind wie definiert: fib(0) -> 0 fib(1) -> 1 fib(2) -> 1 fib(3) -> 2 fib(4) -> 3 fib(5) -> 5 fib(6) -> 8 ... fib(10) -> 55 ... fib(15) -> 610""" return 1
def fibtab(n): """erzeugt eine Tabelle der Fibonaccizahlen bis inclusive n. z.B. gibt fibtab(10) folgendes aus: [0, 1, 1, 2, 3, 5, 8] oder fibtab(100): [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] Hinweis: verwenden Sie als Zeilenumbruch ", " beim print, also print(wert, end=', ') außer natürlich beim letzten Wert, hier ist "]" gefordert. """ print("[0, 1, 1, 2, 3, 5, 8]")
def sum_3_5(max): """ bilde Summe der Vielfachen von 3 und 5 kleiner als max. Beispielsweise liefert sum_3_5(10) 23, weil die Vielfachen von 3 < 10 sind 3 + 6 + 9 = 18 die Vielfachen von 5 < 10 sind 5 18 + 5 = 23 sum_3_5(20) liefert 78, weil 3+ 6+9+ 12+15+18=63 5+ 10+ =15 (15 ist in obiger Liste schon enthalten!) sum_3_5(25) liefert 143, weil 3+ 6+9+ 12+ 18+ 21+24=93 (Vielfache von 5 stehen darunter) 5+ 10+ 15+ 20+ =50 sum_3_5(100) liefert 2318 (ohne Beweis) """ return 23
def minquad(zahl): """finde die nächstkleinere oder gleichgroße ganze Zahl, die eine Quadratzahl ist. Beispiele: minquad(16) -> 16 (weil 4 * 4 = 16 <= 16) minquad(24) -> 16 (weil 4 * 4 = 16 <= 24) minquad(25) -> 25 (weil 5 * 5 = 25 <= 25) minquad(26) -> 25 (weil 5 * 5 = 25 <= 26) """ return zahl
def dreieck(a, w): """zeichnet ein gleichseitiges Dreieck der Seitenlänge a, gedreht um den Winkel w. w = 0 bedeutet, dass die eine Seite horizional ist. w = 90 bedeutet, dass das Dreieck nach LINKS um 90° gedreht ist, d.h. eine Seite ist vertikal. Das Dreieck soll rechts neben des angegebenen Punktes gezeichnet werden. """ pass
def dreieck_an_pos(a, w, x, y): """zeichnet ein Dreieck mit Hilfe der Funktion dreieck(a, w) an der Position x, y.""" pass
Hier folgt ein Beispielaufruf für die Schaltjahrfunktion:
def test_ist_schaltjahr(): for jahr in (1000, 1581, 1582, 1900, 1999, 2003): assert not ist_schaltjahr(jahr) for jahr in (1996, 2000, 2004): assert ist_schaltjahr(jahr) print("ist_schaltjahr ok")
Sollte ist_schaltjahr() richtig implementiert sein, dann müsste "ist_schaltjahr ok" ausgegeben werden. Andernfalls wird das Programm bei einer der assert-Anweisungen abgebrochen werden. assert verwendet man als Programmierer um Bedingungen zu prüfen, die, falls sie nicht erfüllt sind, auf einen Programmierfehler hinweisen. Als Bedingung kann alles rechts neben dem assert stehen, das True ("alles ok") oder False liefert. Die Testaufrufe für alle Funktionen sollten dann etwa so zusammengefasst werden:
def main(): """Hauptprogamm zum Testen aller Funktionen""" test_ist_dreieck() test_ist_quadrat() test_ist_schaltjahr() test_fib() test_sum_3_5() test_minquad() test_dreieck() test_dreieck_an_pos()
Dieses main() muss natürlich auch erst aufgerufen werden (keine Einrückung):
main()
Wenn Sie das Programm laufen lassen, dann sieht sie Ausgabe, wenn alles funktioniert (sinngemäß) so aus:
ist_dreieck ok ist_quadrat ok ist_schaltjahr ok fib ok sum_3_5 ok minquad ok
Die Funktionen test_dreieck() sowie test_dreieck_an_pos() bewirken eine Zeichnung der folgenden Art (je nach Aufrufe):
Hier waren es die Aufrufe:
def test_dreieck(): reset() dreieck(60, 0) dreieck(60, 90) dreieck(60, -60)
def test_dreieck_an_pos(): dreieck_an_pos(70, 0, 50, 50) dreieck_an_pos(70, 180, -50, -50)
Es ist also "optische Kontrolle" nötig.
Labels: Aufgabe, POS1-1, Python
# Eingestellt von Harald R. Haberstroh @ 15:12 0 Kommentare
Donnerstag, 11. November 2010
Code-Kata
Beim Karate (z.B. Karatedo Doshinkan) gibt es Kata (dt. "Form", siehe auch Kata auf Wikipedia), eine spezielle Übungsform, bei der man als Training gegen einen oder mehrere (vorgestellte) Gegner kämpft. Dabei ist der Bewegungsablauf aber stilisiert und fix vorgegeben. Das oftmalige Wiederholen der Bewegungsabläufe in Form von Kata ist unerlässlich für den persönlichen Fortschritt. Denn nur Übung macht den Meister.
Auch Programmieren beherrscht man nur durch ständiges Training. Nur durch Üben wird man auch hier zum Meister. Aber nicht nur durch den Kampf (Programmieren für das Geschäft) sondern auch durch Katas. Diese Idee für's Programmieren hat Dave Thomas von den Pragmatischen Programmieren (meines Wissens) erstmalig aufgegriffen und publiziert: Code Kata
Sehr empfehlenswert für alle, die Programmieren meistern wollen.
Die Idee der Code Kata fasziniert und berührt mich besonders, da ich selber jahrelang
trainiert habe.
Labels: allgemeines, C, C#, C++, Java, POS1-1, POS1-2, PR5
# Eingestellt von Harald R. Haberstroh @ 16:00 0 Kommentare
Freitag, 15. Oktober 2010
Listings (Source-Code drucken)
Sollten Sie Source Code in gedruckter Form abliefern (müssen), dann sollte ein Listing etwa so aussehen:
Das Listing sollte folgende Eigenschaften aufweisen:
- Autor und Dateiname ist sofort ersichtlich
- Seitennummern werden gedruckt
- Syntax-Hilighting: Schlüsselworte, Kommentare usw. sollten unterschiedlich formatiert sein
- Querformat mit zwei Spalten, um Papier zu sparen (Zwei Seiten auf eine drucken)
- Es muss ein "fixed font" (z.B. Courier) verwendet werden, d.h. jedes Zeichen hat die selbe Breite (ausgenommen String-Konstante)
- Optional sollen Zeilennummern gedruckt werden (siehe Beispiele unten).
Beispiel mit Zeilennummern:
Beispiel mit Zeilennummern, nur jede 5. Zeile bekommt eine Nummer:
Unter Linux können Sie den Befehl a2ps (ASCII to PostScript, 2 = two = to, daher a2ps) verwenden.
Beispiele:
Die Datei dreieck.py wird auf dem Drucker hpg1 ohne Zeilennummern gedruckt.
a2ps --line-numbers=1 -Phpg2 dreieck.py newprog.py
Die Dateien dreieck.py und newprog.py werden am Drucker hpg2 mit Zeilennummern gedruckt.
a2ps --line-numbers=5 -Phpg3 dreieck.py newprog.py
Die Dateien dreieck.py und newprog.py werden am Drucker hpg3 mit Zeilennummern gedruckt, wobei nur jede fünfte Zeilennummer gedruckt wird.
Weitere Optionen zu a2ps finden Sie in der man-Page (man a2ps).
Die meisten IDEs (z.B. eclipse oder netbeans) und viele Editoren bieten ähnliche Möglichkeiten, jedoch passt bei a2ps der Ausdruck praktisch immer (abgesehen davon, dass a2ps nur ASCII-versteht und damit Probleme mit Umlauten hat, aber damit kann man leben).
Labels: allgemeines, POS1-1, POS1-2, PR5
# Eingestellt von Harald R. Haberstroh @ 10:22 0 Kommentare
Mittwoch, 6. Oktober 2010
Header für Python-Programme (POS1: 1BHIF, 2AHIF, 2CHIF)
Jedes Python-Programm bzw. Python-Modul muss einen Header der Form
""" author: AUTOR matnr: EVIDENZNUMMER file: DATEINAME desc: ZWECK date: DATUM class: KLASSE catnr: KATALOGNUMMER """
besitzen. Zum Beispiel:
""" author: Neubauer, Claudia matnr: d09666 file: fibonacci.py desc: Gibt die Fibonacci-Zahlen bis zu einer gegebenen Grenze aus date: 2010-10-06 class: 2AHIF catnr: 33 """
Labels: POS1-1, POS1-2, Python
# Eingestellt von Harald R. Haberstroh @ 14:51 0 Kommentare
Abonnieren Kommentare [Atom]













