Shellskripte mit Aha-Effekt: Zahlenspiele
Zahlenumwandlung mit printf
Was aber, wenn kein bc zur Verfügung steht, weil er auf dem Kundenserver nicht installiert wurde? Nachinstallation auf einem fremden System geht ja nun mal nicht. Wenn eine bash verfügbar ist, hilft bei der Umwandlung von Dezimalwerten in Hex-Zahlen die Funktion printf. Diese Zeilen definieren die Umwandlung als Shell-Funktion. Der Aufruf X=$(Hex 123) ; echo $X
liefert dann wunschgemäß den Wert 7B:
01 Hex() # (Val) 02 { 03 VAL=$1 04 printf "%0X" $VAL 05 }
Bei der Umwandlung von Dezimalzahlen in Binärwerte ist es nicht ganz so einfach. Hier gilt es, wirklich zu programmieren. Es kommt das Horner-Schema für die Zahlenumwandlung zum Einsatz, das prinzipiell die Konvertierung beliebiger Zahlensysteme erlaubt. Das Horner-Schema dient vor allem zum Berechnen von Polynomen. Hier tritt die Zahlenbasis an die Stelle der Unbekannten, und die ermittelten Ziffern sind Koeffizienten des Polynoms. Klar wird das bei der Polynomschreibweise einer Zahl, etwa 3514 = 3*103 + 5*102 + 1*101 + 4.
Um beispielsweise die Dezimalzahl 123 ins Binärsystem umzuwandeln, hilft folgendes Schema:
- Die Zahl wird durch 2 geteilt mit Rest.
- Der Divisionsrest wird notiert.
- Ist der ganzzahlige Quotient = 0, ist man fertig, andernfalls nimmt man ihn als neue Zahl und wiederholt den Durchlauf.
Das heißt also:
123 : 2 = 61 | Rest: 1 |
61 : 2 = 30 | Rest: 1 |
30 : 2 = 15 | Rest: 0 |
15 : 2 = 7 | Rest: 1 |
7 : 2 = 3 | Rest: 1 |
3 : 2 = 1 | Rest: 1 |
3 : 2 = 1 | Rest: 1 |
1 : 2 = 0 | Rest: 1 |
Um die endgültige Binärzahl zu erhalten, schreibt man die Divisionsreste beginnend von letzen Wert (unten) bis zum ersten Wert (oben) nieder. Die Berechnung liefert dann für das Beispiel 1111011.
Ein Shellskript realisiert das Aufschreiben von unten nach oben dadurch, dass der Programmierer den neu ermittelten Rest stets vor das bisherige Resultat schreibt. Außerdem ersetzt er die Division durch 2 mit einem Schiebebefehl und die Ermittlung des Rests durch das Abschneiden der letzten Stelle mittels UND-Verknüpfung. Beide Operationen sind meist schneller als die Division. Im Übrigen kommt der geschilderte Algorithmus eins zu eins zur Anwendung.
Das folgende Skript definiert wieder eine Shell-Funktion (Zeile 01). Zeilen 03 und 04 initialisieren Startwert und Resultat. Die Schleife (Zeilen 05 bis 08) läuft durch, bis der Quotient 0 geworden ist. Zeile 06 ermittelt den Divisionsrest durch eine UND-Verknüpfung mit 1 und setzt die letzte Stelle vor die Ergebnis-Variable. Zeile 07 dividiert den Wert VAL
per Rechtsschieben durch 2. Das Echo-Kommando in Zeile 09 gibt nur den Wert zurück - ohne Zeilenvorschub.
01 Binary() # (VAL) 02 { 03 VAL=$1 04 RESULT="" 05 while [ $VAL -ne 0 ] ; do 06 RESULT=$(( $VAL & 1 ))$RESULT 07 VAL=$(( $VAL >> 1 )) 08 done 09 echo -n $RESULT 10 }
Ein Probelauf zeigt die gewünschten Ergebnisse:
$ X=$(Binary 123) ; echo $X 1111011 $ X=$(Binary 65) ; echo $X 1000001 $ X=$(Hex 123) ; echo $X 7B $ X=$(Hex 65) ; echo $X 41