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 sein

def 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 liste

def 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:

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

This page is powered by Blogger. Isn't yours?

Abonnieren Kommentare [Atom]