Umgebungen
Aus ProgrammingWiki
Wiki-Quelltext dieser Seite.
<language>Scheme</language>
[[Programmierparadigmen_-_Computerübungen|Zurück zur Übungsübersicht]]
Gegenstand dieser Übung sind Umgebungen. Arbeiten Sie das Vorlesungsskript durch, erproben Sie die darin enthaltenen Beispiele und bearbeiten Sie die angegebenen Übungsaufgaben. Weiteres Übungsmaterial, das auch Inhalte früherer Computerübungen enthält, finden Sie in den folgenden Aufgaben.
<code>;Bereich für Übungen aus dem Buch </code>
<run>;Ausführungsbereich für Übungen aus dem Buch</run>
==Dualzahl==
Schreiben Sie eine Prozedur <tt>(dualzahl x)</tt>, die eine dezimale Gleitkommazahl in eine duale Gleitkommazahl umwandelt. Die Dualzahl soll als Zeichenkette zurückgegeben werden.
'''Aufrufbeispiele:'''
> (dualzahl 0)
"0"
> (dualzahl 123)
"1111011"
> (dualzahl 10.125)
"1010.001"
> (dualzahl -0.346)
"-0.0101100010010011"
'''Hinweise''': Die nachfolgende Darstellung demonstriert den Algorithmus zur Umwandlung:
'''Gleitkommazahl: 10,125'''
{|
|-
|ganz: 10||gebrochen: 0,125
|-
|10 : 2 = 5 Rest 0||0,125 * 2 = 0.25
|-
| 5 : 2 = 2 Rest 1||0,250 * 2 = 0.5
|-
| 2 : 2 = 1 Rest 0||0,500 * 2 = 1,0
|-
| 1 : 2 = 0 Rest 1|| 1,0 ⇒ Ende
|-
| 0 ⇒ Ende
|}
'''Dualzahl: 1010,001'''<br />
Definieren Sie geeignete Hilfsprozeduren zur Ermittlung der ganzen bzw. gebrochenen Teilzeichenkette im gesuchten “Dualstring”. Verwenden Sie Typkonvertierungen, wie number->string und string->list, um diese Teile zu extrahieren. Die Basis der internen Darstellung einer Dezimalzahl muss nicht 10 sein! Deshalb liefern gewisse Operationen mit Zahlen u. U. “merkwürdige” Effekte. Nach der Extraktion des Vor- und Nachkommateils der gegebenen Zahl findet eine Zahlenrechnung statt. Beachten Sie, dass auch “Dualbrüche” periodisch sein können! Brechen Sie den Algorithmus, falls notwendig, nach 16 dualen Nachkommastellen ab! Nutzen Sie statt floor und ceiling besser truncate zum Abschneiden der Nachkommas tellen und machen Sie sich zur Unterstützung mit den vordefinierten Prozeduren <tt>quotient</tt>, <tt>remainder und <tt>inexact->exact</tt> vertraut!
<popup name="Lösungsbereich">
<code>;(dualzahl zahl)</code>
<run>(dualzahl 10.125)</run>
<run>(dualzahl 0)</run>
<run>(dualzahl -0.346)</run>
<check>(equal? "111111.1111" (dualzahl 63.9375))</check>
</popup>
==Nullstellen==
Entwickeln Sie die Prozedur <tt>(nst f min max dx)</tt>, die zu einer beliebigen stetigen Funktion f alle Nullstellen im Intervall [min ; max] als Liste zurückgibt. Die Nullstellen sollen mit einer Genauigkeit von 6 Dezimalstellen ermittelt werden.
'''Lösungsgedanken''':
#Zerlege das Intervall [min ; max] in Teilintervalle der Breite dx.
##Prüfe an den Intervallgrenzen jedes Teilintervalls die Vorzeichen der Funktionswerte.
##Bei entgegengesetzten Vorzeichen muss die stetige Funktion in diesem Intervall eine Nullstelle haben. Ermitteln Sie diese durch Intervallschachtelung und füge sie der Lösungsmenge (Liste) hinzu.
##Setze die Suche in den Nachbarintervallen fort, bis die rechte Intervallgrenze max erreicht ist.
'''Aufrufbeispiele:'''
> (nst (lambda (x) (sin (- x 1))) -10 10 .1)
(-8.424778 -5.283185 -2.141593 1.0 4.141593 7.283185)
> (nst (lambda (x) (- (* 3 x x) (* 4 x) 17)) -10 10 1)
(-1.805399 3.138733)
> (nst (lambda (x) (- (* 0.5 x x) 4)) -10 10 1)
(-2.828427 2.828427)
<code>;Ihre Nullstellenfunktion (nst f min max dx)</code>
<run>(nst (lambda (x) (sin (- x 1))) -10 10 .1)</run>
<run>(nst (lambda (x) (- (* 3 x x) (* 4 x) 17)) -10 10 1)</run>
<run>(nst (lambda (x) (- (* 0.5 x x) 4)) -10 10 1)</run>
<check>
(define listenvergleich
(lambda(l1 l2)
(cond
[(and (null? l1) (null? l2)) #t]
[(not (= (length l1) (length l2))) #f]
[(and (list? (car l1)) (list? (car l2)))
(if (listenvergleich (car l1) (car l2))
(listenvergleich (cdr l1) (cdr l2))
#f)]
[(not (equal? (car l1) (car l2))) #f]
[else (listenvergleich (cdr l1) (cdr l2))]
)
)
)
(and
(listenvergleich (nst (lambda (x) (sin (- x 1))) -10 10 .1) '(-8.424778 -5.283185 -2.141593 1.0 4.141593 7.283185))
(listenvergleich (nst (lambda (x) (- (* 3 x x) (* 4 x) 17)) -10 10 1) '(-1.805399 3.138733))
(listenvergleich (nst (lambda (x) (- (* 0.5 x x) 4)) -10 10 1) '(-2.828427 2.828427)))</check>
'''Lösungsvorschlag'''. Bitte arbeiten Sie ihn durch und erproben Sie die Prozedur. Dann werden Sie auch Schwachstellen des Vorschlags erkennen, denn nicht in jedem Fall werden die Nullstellen auch wirklich gefunden.
<code>
(define my-nst
(lambda (f anfang ende dx )
(letrec
((intervall-sucher
(lambda ( von bis )
(cond
((= bis ende ) '())
(( not (= ( signum ( f von )) ( signum ( f bis ))))
( cons
(/
(round (* ( intervallhalbierung von bis ) 1000000))1000000)
(intervall-sucher bis (+ bis dx ))))
(( <= (+ bis dx ) ende )( intervall-sucher bis (+ bis dx )))
(else
(intervall-sucher bis ende )))))
(intervallhalbierung
(lambda ( links rechts )
(let * ((mitte (/ (+ links rechts ) 2.0))
( l ( f links ))( m ( f mitte ))( r ( f rechts )))
( cond
(( < ( abs ( - l r )) 0.0000001) links )
(( not (= ( signum l ) ( signum m )))
( intervallhalbierung links mitte ))
(else
(intervallhalbierung mitte rechts )))))))
(intervall-sucher anfang (+ anfang dx)))))
(define signum
(lambda ( i )
(cond
(( < i 0) -1)
((= i 0) 0)
(( > i 0) 1))))
</code>
<run>;Testbereich der gegebenen nst Funktion</run>
==Integral==
Schreiben Sie die Prozedur <tt>(integral f li re dx)</tt>, die das bestimmte Integral der Funktion f im Intervall [li ; re] ermittelt. Die Fläche unter dem Graphen dieser Funktion soll dazu mit möglichst vielen Trapezflächen angenähert werden, deren (kleine) Breite dx beträgt.
'''Hinweise:'''
Beginnen Sie am besten damit, das bestimmte Integral von <math>f : x \rightarrow 2x^{2} + 1</math> von <math>x_{min}=4</math> bis <math>x_{max}=6</math> (s. Beispiel 1 unten) analytisch zu berechnen. Das Ergebnis ist 103.3...
'''Rekursive Idee:'''
Fläche = 0, wenn li+dx > re, sonst Fläche = Trapezfläche mit Breite dx + Fläche Rest
'''Aufrufbeispiele:'''
> (integral (lambda (x) (+ (* 2 x x) 1)) 4 6 1)
104
> (integral (lambda (x) (+ (* 2 x x) 1)) 4 6 0.1)
103.33999999999985
> (integral (lambda (x) (+ (* 2 x x) 1)) 4 6 0.01)
103.33339999999914
<code>;(integral funktion untergrenze obergrenze bereich</code>
<run>(integral (lambda (x) (+ (* 2 x x) 1)) 4 6 1)</run>
<run>(integral (lambda (x) (+ (* 2 x x) 1)) 4 6 1)</run>
<run>(integral (lambda (x) (+ (* 2 x x) 1)) 4 6 0.01)</run>
<check>(and
(= (integral (lambda (x) (+ (* 2 x x) 1)) 4 6 1) 104)
(= (integral (lambda (x) (+ (* 2 x x) 1)) 4 6 0.1) 103.33999999999985)
(= (integral (lambda (x) (+ (* 2 x x) 1)) 4 6 0.01) 103.33339999999914))
</check>
[[Programmierparadigmen_-_Computerübungen|Zurück zur Übungsübersicht]]