Umgebungen

Aus ProgrammingWiki

Wiki-Quelltext dieser Seite.

<language>Scheme</language>
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>
<eval>;Ausführungsbereich für Übungen aus dem Buch</eval>



==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!

<code>;(dualzahl zahl)</code>
<eval>(dualzahl 10.125)</eval>
<eval>(dualzahl 0)</eval>
<eval>(dualzahl -0.346)</eval>
<check>(equal? "111111.1111" (dualzahl 63.9375))</check>

==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.<br />
'''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)
'''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>
<eval>;Testbereich der gegebenen nst Funktion</eval>

<code>;Ihre Nullstellenfunktion (nst f min max dx)</code>
<eval>(nst (lambda (x) (sin (- x 1))) -10 10 .1)</eval>
<eval>(nst (lambda (x) (- (* 3 x x) (* 4 x) 17)) -10 10 1)</eval>
<eval>(nst (lambda (x) (- (* 0.5 x x) 4)) -10 10 1)</eval>
<check>(and 
(listenvergleich (nst (lambda (x) (+ (* x x ) -2) -10 10 1) '(-1 1))
(listenvergleich (nst (lambda (x) (+ (* 0.5 x x ) (* -0.5 x) -0.001)) -10 10 3) '(-0.001996 1.001996))</check>

==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...<br />
'''Rekursive Idee:'''<br />
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>
<eval>(integral (lambda (x) (+ (* 2 x x) 1)) 4 6 1)</eval>
<eval>(integral (lambda (x) (+ (* 2 x x) 1)) 4 6 1)</eval>
<eval>(integral (lambda (x) (+ (* 2 x x) 1)) 4 6 0.01)</eval>