Bergervei/Dualzahlen

Aus ProgrammingWiki

Wiki-Quelltext dieser Seite.

<language>Scheme</language>
== Umwandlung einer dezimalen Gleitkommazahl in eine Dualzahl ==

Die nachfolgende Abbildung demonstriert die Algorithmen für die Umwandlung des ganzzahligen bzw. gebrochenen Anteils der Dezimalzahl in den jeweiligen Anteil der Dualzahl:

<blockquote>[[Bild: DezimalToDual1.gif]]</blockquote>

Dualzahlen mit Nachkommastellen sowie ihre ganzzahligen und gebrochenen Anteile werden als Zeichenketten (''Strings'') repräsentiert.

<code id="4d6029bf6b39c">
(define frac
  (lambda (x)
    (- x (floor x))))

(define dualganz
  (lambda (x)
    (letrec
        ([dual
          (lambda (n)
            (if (= n 0)
                ""
                (string-append (dual (quotient n 2)) 
                               (number->string (inexact->exact (modulo n 2))))))])
      (if (= (floor x) 0)
          (number->string 0)
          (dual (floor x))))))

(define dualgebr
  (lambda (x)
    (letrec
        ([dual
          (lambda (n m)
            (if (or (= n 0) (= m 32))
                ""
                (string-append (number->string (inexact->exact (floor (* n 2)))) 
                               (dual (frac (* n 2)) (+ m 1)))))])
      (dual (frac x) 0))))

(define dualzahl
  (lambda (x)
    (cond
      [(< x 0) #f]
      [(= (frac x) 0) (dualganz x)]
      [else
       (string-append (dualganz x) "." (dualgebr x))])))
</code>

<run id="4d6029bf6b4aa">
(dualzahl 12.625)
</run>

== Umwandlung einer Dualzahl in eine dezimale Gleitkommazahl ==

In ähnlicher Weise können auch Dualzahlen mit Nachkommastellen, die ebenfalls als Zeichenketten vorliegen, in Dezimalzahlen konvertiert werden. Das nachfolgende Schema verdeutlicht wieder die entsprechenden Algorithmen:

<blockquote>[[Bild: DualToDezimal1.gif]]</blockquote>

Die Prozedur <tt>dualteilen</tt> teilt die Zeichenkette, die eine Dualzahl repräsentiert, in zwei Teilketten auf.
Diese entsprechen dem ganzen bzw. gebrochen Anteil der Dualzahl. Bei dieser Teilung wird eine Syntaxkontrolle vorgenommen.
Die Zeichenkette des ganzen Anteils wird zur besseren Weiterverarbeitung invers (d.h. in umgekehrter Ziffernfolge) zurückgegeben.

<code id="4d618b12ab4e8">
(define dualteilen
  (lambda (str)
    (letrec
        ([teilen
          (lambda (pos dp paar)    
            (cond
              [(= pos (string-length str)) paar]
              [(not dp)
               (case (string-ref str pos)
                 ([#\0 #\1] 
                  (teilen (+ pos 1) #f 
                          (cons (string-append (substring str pos (+ pos 1)) (car paar)) (cdr paar))))   
                 ([#\.]
                  (teilen (+ pos 1) #t paar))
                 (else #f))]
              [else
               (case (string-ref str pos)
                 ([#\0 #\1] 
                  (teilen (+ pos 1) #t 
                          (cons (car paar) (string-append (cdr paar) (substring str pos (+ pos 1))))))   
                 (else #f))]))])
      (teilen 0 #f (cons "" "")))))

(define dezimalzahl
  (lambda (str)
    (letrec
        ([potsumme
          (lambda (str pos pot op)
            (if (= pos (string-length str))
                0
                (+ (* (string->number (substring str pos (+ pos 1))) pot)
                   (potsumme str (+ pos 1) (op pot 2) op))))])
      (let ([paar (dualteilen str)])
        (if paar
            (exact->inexact (+ (potsumme (car paar) 0 1 *) (potsumme (cdr paar) 0 1/2 /)))
            #f)))))
</code>

<run id="4d6029bf6b51b">
(dezimalzahl "1100.101")
</run>