Modul „Einführung in die Informatik“: Aufgaben zur Großübung 4 Thema: Python I 1) a) Berechnung der Fakultät (von einer ganzen Zahl >= 0) Nichtrekursive Berechnung der Fakultät (vgl. Aufg.-komplex Struktogramme, Aufg. 5) Es ist ein Python-Skript zu entwickeln für die nichtrekursive Berechnung der Fakultät n_fakultaet = n! =1*2*…*(n-1)*n (n>=0, ganz), wobei per definitionem gilt: 0! = 1 Die Eingabe und die Resultatausgabe sollen im Hauptprogramm erfolgen. Wenn n<0 eingegeben wird (Fehler), ist die Eingabe zu wiederholen (mehrfache Fehleingaben sind nicht auszuschließen). Die Fakultät soll in einer gesonderten Funktion berechnet werden. In der Funktion ist nicht mit globalen Variablen zu arbeiten (d.h. n ist an die Funktion zu übergeben). Es ist je ein vollständiges Python-Skript zu schreiben: a1) unter Verwendung einer Zählschleife In diesem Skript ist das Hauptprogramm als Testrahmen zu schreiben, um die Fakultäts-Funktion in Aufgabe 2 nutzen zu können. Dazu ist das Skript in W:\Python unter der Bezeichnung nfak_for_Modul.py zu speichern. in der Großübung wird die Abarbeitung von a1) anhand des Debuggers erläutert siehe dazu auch: Y:\lehre\Modul_Einf_in_die_Informatik_WS112_Jung\Pooluebungen \Lehrfolien_zu_Python\Arbeit mit dem Python-Debugger.pdf a2) unter Verwendung einer Abweisschleife a3) unter Verwendung einer nachgeahmten Nichtabweisschleife. Hinweis zu a3): Es ist zu beachten, dass Python keine Nichtabweisschleife besitzt. Man kann aber eine Nichtabweisschleife nachbilden mit „while True“ als Kopf, d.h. der Schleifenkörper wird immer betreten, und einer if-Anweisung als Schleifenfuß, die den Schleifenabbruch regelt. ------------------------------ b) Rekursive Berechnung der Fakultät (vgl. Vorlesungsskript Informatik05-Algorithmen.pdf , S.11 sowie Informatik08-Python-2.pdf, S.8) Bemerkung: In der Vorlesung Informatik08-Python-2.pdf wurde n>=1 vorausgesetzt, jetzt aber n>=0. Es ist ein Python-Quelltext zu schreiben für die rekursive Berechnung der Fakultät n_fakultaet = n*(n-1)! (n>=0, ganz), wobei wieder per definitionem gilt: 0! = 1 Die Eingabe und die Resultatausgabe sollen im Hauptprogramm erfolgen. Die Fakultät selbst ist in einer gesonderten Funktion (ohne globale Variable) zu berechnen. (Auf eine Eingabeprüfung – wie unter 1.a) - soll hier der Kürze halber verzichtet werden.) Hinweis: In der folgenden Folie folie_rekursive_fakultaet.doc wird nochmals erläutert, wie die rekursiven Funktionsaufrufe abgearbeitet werden (diese Folie ist auch im Festplattenverzeichnis Lehrfolien_zur_Uebung gespeichert). in der Großübung wird die Abarbeitung anhand des Debuggers erläutert 1 Zur rekursiven Lösung der Aufgabe nfak = n! ;n>=0, ganz - Trockentest am Beispiel n = 3 : Eingabe: 3 nfak = fakrek(3) Funktionsaufruf vom Hauptprogramm aus: 6 fakrek(3): return 3 * fakrek(2) 3*2 1. rekursiver Funktionsaufruf: 2 fakrek(2): return 2 * fakrek(1) 2*1 (1) (3) 2. rekursiver Funktionsaufruf: 1 fakrek(1): return 1 * fakrek(0) 1*1 3. rekursiver Funktionsaufruf: 1 (2) Fortsetzung nach Rücksprung ins Hauptprogramm mit: Rückgabewert 6 fakrek(0): return 1 Der Ausdruck n*fakrek(n) in der returnAnweisung lässt sich nach dem „Rekursionsabstieg“ (1) über immer einfachere Versionen des Ausdrucks hier erstmals lösen, d.h. die Fakultäts-Funktion wird erstmals bis zum Ende abgearbeitet. Von diesem „Rekursionsanfang“ (2) aus wird nun die Lösung der ursprünglichen Aufgabe aufgebaut. Beim jetzt beginnenden „Rekursionsaufstieg“ (3) werden schrittweise rekursiv die erhaltenen Sublösungen eingesetzt und jeder Funktionsaufruf bis zum Ende abgearbeitet. 2 2) Summe dreier Fakultäten: a! + b! + c! (a, b, c>=0 und ganz) Es ist ein Python-Skript zur Berechnung der Summe dreier Fakultäten: a! + b! + c! (Dieses Skript ist in W:\Python zu speichern.) zu entwickeln. Im Hauptprogramm sind die drei ganzen Zahlen a, b, c (>=0) einzulesen sowie die berechnete Summe auszugeben. Dabei ist die Eingabe zu wiederholen, wenn eine oder mehrere negative Zahlen eingegeben wurden (mehrfache Fehleingaben sind nicht auszuschließen). Zur Berechnung der Summe der drei Fakultäten ist die in Aufgabe 1.a1) geschriebene Funktion zur Berechnung von n! zu nutzen, die mit Testrahmen unter der Bezeichnung nfak_for_Modul.py in W:\Python gespeichert wurde. (Durch mehrfachen Aufruf kann die Summe der drei Fakultäten berechnet werden.) Bemerkung: Das Modul wird gefunden, da beide Quelltexte in W:\Python gespeichert wurden. Andernfalls ist der Systempfad entsprechend einzustellen. Demonstration in der Großübung: - Fehlerhafter Effekt bei Import des Moduls des Moduls nfak_for_Modul (siehe oben), wenn man statt einem Testrahmen ein „normales“ Hauptprogramm verwendet ---------------------------------------------------------------------------------------------------------------------------- 3) Summe von n reellen Zahlen mit Liste als Datenmodell (vgl. Aufgabenkomplex Struktogramme, Aufg. 8.b) 3.a) Gesucht ist die Summe von n reellen Zahlen. Die Anzahl n (n>=1) der Zahlen sei dem Nutzer bekannt und kann somit eingelesen werden. Die Zahlen sollen in eine Liste eingelesen werden. Benutzen Sie nur die Zählschleife. Die Eingabe der n reellen Zahlen soll in einer gesonderten Funktion und die Berechnung der Summe in einer weiteren gesonderten Funktion erfolgen (d.h. zwei Funktionen). In den Funktionen ist nicht mit globalen Variablen zu arbeiten. Im Hauptprogramm sollen die Anzahl n eingelesen, die beiden Funktionen aufgerufen und die Summe als Resultat ausgegeben werden. 3.b) Nur eine Änderung gegenüber 3.a): Die Anzahl der Werte n soll jetzt nicht vom Nutzer eingegeben werden (denn: dieses Vorgehen kann Fehler einschleppen!), sondern Eingabe mit Endeerkennungszeichen vom Typ der eingelesenen Werte (ist in Python nicht unbedingt notwendig, aber in fast allen anderen Sprachen). Konkreter: - keine Abfrage der Anzahl der Werte beim Nutzer - nach letzter eingegebenen Zahl als „nächste Zahl“ eingeben: ENTER Im Quelltext jetzt: - Einlesen der „Zahl“ als String ( mit raw_input( ) ); Endeerkennungszeihen ENTER (entspricht leerem String!) ist damit vom Typ der eingelesenen Werte! - Solange eingelesener String ungleich leerem String (ENTER): eingelesenen String in float-Zahl konvertieren ---------------------------------------------------------------------------------------------------------------------------3 4) Normalisieren von Sound (auf 95% des max. möglichen Lautstärkewertes für 16 bit-Sound) Im Vorlesungsskript Informatik10-Sound.pdf wurde Sound normalisiert, d.h. die Samplewerte (Soundamplituden) so skaliert (verstärkt), dass der max. Samplewert den max. möglichen Wert (für Sound mit 16 bit Sampling-Tiefe) von 32767 erreicht. Allerdings normalisieren nicht alle Soundeditoren (z.B. Audacity) auf 100% des max. möglichen Wertes, sondern lassen oft etwas „Headroom“ frei. Deshalb soll in dieser Aufgabe auf 95% des max. möglichen Wertes, also auf 0.95*32767, normalisiert werden. Bedeutung der Normalisierung von Sound: Das Normalisieren von Sound hat z.B. bei mehreren für eine CD/DVD vorgesehenen Soundfiles den Vorteil, dass die verschiedenen Audiodateien danach als gleich laut empfunden werden und beim Anhören der CD/DVD kein Nachsteuern notwendig ist. Außerdem ist Normalisieren generell nach pegelverändernden Operationen bei der digitalen Soundeditierung sehr sinnvoll, da Rundungsfehler bei Rechenoperationen mit größeren Werten weniger ins Gewicht fallen. Schritte beim Normalisieren von Sound auf 95% des max. Wertes (vgl. Vorlesung): 1. Maximalen Sample-Wert loudest im Soundobjekt ermitteln 2. Ermittlung des Normalisierungsfaktors normFactor, so dass gilt: normFactor * loudest = 0.95*32767 , d.h. normFactor = 0.95*32767/loudest Da hier auf 95% normalisiert wird, muss der Normalisierungsfaktor nicht immer >=1 sein, also nicht immer - wie in der Vorlesung bei 100% - ein Verstärkungsfaktor. 3. Normalisierung aller Samplewerte durch Multiplikation mit normFactor ------------ Aufgabe: - Es ist ein Python-Skript zur Normalisierung eines wav-Soundfile’s auf 95% des maximal möglichen Samplewerts, d.h. auf 0.95*32767, zu entwickeln. Dazu sollen in einem Testrahmen die Dateibezeichnung eines WAV-Soundfiles eingelesen und ein internes Soundobjekt gebildet werden. In einer gesonderten Funktion ist dann das Soundobjekt auf 95% des maximal möglichen Samplewerts zu normalisieren. Das normalisierte Soundobjekt ist schließlich im Testrahmen abzuspielen und in das PythonArbeitsverzeichnis unter einer veränderten Filebezeichnung zu speichern. ---------------------------------------------------------------------------------------------------------------------------- 4 5) Konvertieren einer ganzen Zahl eines Zahlensystems zur Basis B; 2<=B<=36 in eine Dezimalzahl (gemäß Hornerschema) Vorbemerkungen: Gemäß Großübung 1, S. 12, sowie Vorlesungsskript Informatik02-Datenrepraesentation.pdf gilt: Konvertieren von beliebigen Systemen ins Dezimalsystem mittels Hornerschema Eine in einem Positionssystem mit der Basis B dargestellte natürliche Zahl n mit N Stellen N −1 n = ∑ bi * B i i =0 lässt sich mittels Hornerschema wie folgt ins Dezimalsystem konvertieren: n = (...(( bN −1 * B + bN − 2 ) * B + bN −3 ) * B + ... + b1 ) * B + b0 Aus dieser Hornerschema-Formel ergibt sich zunächst folgendes Struktogramm: Im folgenden Struktogramm werden die Dezimalzahl n aus der obigen Formel „dezzahl“ und B „basis“ genannt. Die natürliche Zahl zur Basis B mit N Stellen wird als b bezeichnet, wobei b[j]; j=0, ..., N-1; die j-te Stelle dieser Zahl sei (b[0] sei dabei die niedrigste Stelle). A("Eingabe: Zahlenbasis u. ganze Zahl dieser Basis: ") E(basis, b) N = ziffernanzahl (b) dezzahl = b[N-1] b[j] ... j-te Stelle der Zahl b (j = 0, ..., N-1) i = 2, N, 1 dezzahl = dezzahl*basis + b[N-i] A(b, "entspricht der Dezimalzahl", dezzahl) Aufgabe: Es ist ein Python-Skript zur Konvertierung einer natürlichen Zahl (d.h. ganz und >=0) eines Zahlensystems zur Basis B; 2<=B<=36; in eine Dezimalzahl (gemäß Hornerschema) zu entwickeln. Dabei soll die Eingabe (hier der Kürze halber ohne Eingabeüberprüfung) und Ausgabe in einem Testrahmen erfolgen. Statt Großbuchstaben A, ... , Z sollen auch Kleinbuchstaben a, ... , z möglich sein. Die Konvertierung ist in einer gesonderten Funktion vorzunehmen. In der Funktion ist nicht mit globalen Variablen zu arbeiten. Hinweise zur Lösung: a) Die 26 „Zeichenziffern“ A, ... , Z reichen für die „Ziffern“ 10 bis 35; deshalb 2<=B<=36. Beispiel: Die Zahl 2Z zur Basis 36 besteht also aus den Ziffern 2 und 35 (im Dezimalsystem: 107). 5 b) Da hier aber ein Python-Programm zu schreiben ist, können die Indizes der Hornerschema-Formel nicht einfach übernommen werden: - Zunächst kann man eingegebene Kleinbuchstaben mit der String-Methode upper() in die entsprechenden Großbuchstaben umwandeln. - Da die Zahlen zur Basis B auch „Zeichenziffern“ wie z.B. A, B, ..., Z enthalten können, muss die Zahl zunächst in eine Zeichenkette eingelesen werden. Beispiel: B=16, ganzzahl=2AB9 entsprechende Zeichenkette: zahlstring="2AB9" Die höchstwertige Ziffer ist zahlstring[0]= "2" und hat folglich nicht den Index N-1 wie in der Hornerschema-Formel, sondern den Index 0. Entsprechend hat die niedrigstwertige Ziffer nicht den Index 0, sondern N-1. - Die einzelnen Zeichen des zahlstring müssen getestet werden, ob sie Buchstaben ("A", ..., "Z") oder Ziffernzeichen ("0", "1", ..., "9") sind. Schließlich ist das entsprechende Zeichen in eine int-Zahl zu konvertieren (z.B. "B" in die int-Zahl 11, "4" in die int-Zahl 4). ---------------------------------------------------------------------------------------------------------------------------- 6) Näherungsweise Berechnung der Exponentialfunktion ex (vgl. Aufgabenkomplex Struktogramme, Aufg. 10*) (falls noch Zeit vorhanden) Bemerkung: Hier ist nicht die Funktion exp( ) aus dem Modul math zu nutzen, sondern es soll eine entsprechende Funktion selbst geschrieben werden. Es ist ein Python-Skript zur näherungsweisen Berechnung von ex = exp(x) mit Hilfe der bekannten TAYLOR-Reihe x x2 x3 xn e = 1+ + + + ... + + ... 1! 2! 3! n! x ( konvergiert für | x | < ∞ ) in folgender Weise zu entwickeln: - Eingabe von x - Die näherungsweise Berechnung ist abzubrechen, wenn das nächste Glied der Reihe betragsmäßig kleiner als eine einzulesende Genauigkeitsschranke epsilon ist ( 0 < epsilon < 1 ). - Bei der Berechnung der einzelnen Reihenglieder kann man ausnutzen, dass mit g0 = 1 (erstes Glied der Reihe) für die nächsten Reihenglieder gilt: g i = g i −1 * x i für i = 1, 2, ... Die Ein- und Ausgabe soll im Testrahmen erfolgen. Die Berechnung von ex ist in einer gesonderten Funktion vorzunehmen, in der nicht mit globalen Variablen zu arbeiten ist. Richter 11/11 6