| In der IT-Entwicklung gibt es einige Bereiche, in denen man regelmäßig mit verschiedenen Zahlensystemen zu tun hat. | Codierung von Zahlen im Quelltext, Umwandlungen beim Lesen und Schreiben binärer Daten (z.B. Dateien), Umwandlung von Zahlen in Zeichenketten für die Ausgabe. |
Zahlensysteme
|
Darstellung von Zahlenwerten mit Zeichen |
| Java & Javascript | parseInt, parseFloat, toString |
| Perl | pack, unpack, printf, sprintf |
| PHP | pack, unpack, printf, sprintf, base_convert, decbin, dechex, ... |
| SQL | bin, oct, hex, cast |
| VBA | &H, Oct, Hex, Val |
Zahlensysteme in Perl |
|
Quelltext:● Zahlen mit führender Ziffer '0' werden als Octalzahl (Basis 8) interpretiert.● Zahlen mit führender Dezimalziffer > '0' werden als Dezimalzahl (Basis 10) interpretiert. ● Zahlen mit führenden Zeichen '0x' werden als Hexadezimalzahl (Basis 16) interpretiert. ● Zahlen mit führenden Zeichen '0b' werden als Binärzahl (Basis 2) interpretiert. ● In Strings kann man Zeichen auch mit ihrer → Code-Zahl eingeben. Zahlen nach \ werden octal interpretiert, Zahlen nach \x hexadezimal. Dezimale Codes einzelner Zeichen kann man mit Funktion chr() oder pack() verwenden, z.B. zur Codierung von Bytes beliebiger Werte in einem String. ● Mit pack() ist auch die Verwendung von Binärzahlen möglich. Die Bits werden einzeln als String aus "0" und "1" angegeben. Fehlende Bits werden rechts mit 0-Bits ergänzt. |
Beispiele:
$x=011; # 9.
$x=11; # 11. $x=0b11; # 3. $x=0x11; # 17. $s="ABC"; # 'ABC' $s="\101BC"; # 'ABC' $s="\x41BC"; # 'ABC' $s=chr(65)."BC"; # 'ABC' $s=pack("c*",65,66,67); # 'ABC' $s=pack("H*","414243"); # 'ABC' $b=pack("B*","10000001"); # Byte 0x81 |
Codierung:Die Funktionen pack() und unpack() führen alle anfallenden Umwandlungs-Aufgaben durch. Diese Funktionen sind so erfolgreich, dass sie auch in andere Programmiersprachen übersiedelt wurden.● pack() wird eingesetzt, um Zahlen binär zu codieren, um sie z.B. in Binär-Dateien zu schreiben. ● Das Beispiel rechts zeigt die Binär-Codierung der Dezimalzahl 123 mit verschiedenen Optionen von pack(). In der Folge-Zeile jeweils die erzeugten Daten-Bytes in Hex-Darstellung. ● Beachten sie, dass die Bytes normalerweise in umgekehrter Reihenfolge gespeichert werden, d.h. das niedrigst-wertige Byte zuerst, das höchstwertige Byte zuletzt. ♦ Details zur Verwendung der Funktionen pack() und unpack() ♦ Details zur Codierung von Gleitkomma-Zahlen nach IEEE-754 |
Beispiele:
$n=123;
$s2=pack("S",$n); # Ganze Zahl 'short' -> # 2 Bytes: 7B 00 $s4=pack("L",$n); # Ganze Zahl 'long' -> # 4 Bytes: 7B 00 00 00 $s4=pack("f",$n); # Gleitkomma 'single' -> # 4 Bytes: 00 00 F6 42 $s8=pack("d",$n); # Gleitkomma 'double' -> # 8 Bytes: 00 00 00 00 00 C0 5E 40 |
Decodierung:● unpack() wird z.B. eingesetzt, um Binär-Dateien zu lesen und gelesene Bytes (Bitmuster) in verwendbare Daten (z.B. Zahlen) zu decodieren.● Das Beispiel rechts zeigt die Decodierung eines Binär-Strings mit verschiedenen Optionen von unpack(). ● Die Bytes des Strings werden hier zuerst als Quelltext (mit Octalzahlen) eingegeben. Alternativ kann man dazu die Funktion pack() verwenden ● Die Funktion entnimmt aus dem String nur so viele Bytes wie benötigt, d.h. "S" (short) erzeugt eine ganze Dezimalzahl aus den ersten beiden Bytes, "L" eine ganze Dezimalzahl aus den ersten 4 Bytes, "f" eine Gleitkommazahl aus 4 Bytes, und "d" eine Gleitkommazahl aus allen 8 Bytes. ● Das Template "H*" eignet sich gut zur Erzeugung lesbarer Hex-Strings (dump) aus beliebig langen Binärdaten-Strings. ● Bei der Decodierung wird die übliche Byte-Reihenfolge angenommen, d.h. das niedrigst-wertige Byte zuerst. pack und unpack bieten jedoch auch Optionen für die umgekehrte Byte-Reihenfolge. ♦ Details zur Verwendung der Funktionen pack und unpack ♦ Details zur Codierung von Gleitkomma-Zahlen nach IEEE-754. |
Beispiele:
$s="\1\2\3\4\5\6\7\10";
$s=pack("c8",1,2,3,4,5,6,7,8); # 8 Bytes: 01 02 03 04 05 06 07 08
$n=unpack("S",$s);
# 513.
$n=unpack("L",$s);
# 67305985.
$n=unpack("f",$s);
# 1.5399896E-36
$n=unpack("d",$s);
# 5.44760372201161E-270
$t=unpack("H*",$s.chr(16).chr(255));
# 00010203040506070810FF
|
|
Vorsicht !
Einige Optionen der Funktionen pack()
und unpack() sind von der Umgebung (Betriebssystem)
abhängig. Je nach System kann z.B. die Länge der Variablen oder
die Reihenfolge der Bytes varieren.
|
Testen sie daher nach Möglichkeit ihre Programme bzw. die codierten / decodierten Daten auf allen erreichbaren Systemen ! |
Formatierung eines Zahlen-Strings:• Die Funktion printf() führt die Ausgabe formatierter Strings aus und bietet dafür zahlreiche Optionen.• Funktion sprintf() liefert den formatierten String für weitere Verarbeitung. Rechts einige Beispiele mit den Optionen "%d" für Ganze Zahlen, "%f" für Gleitkomma-Zahlen und "%X" für Hexadezimal-Zahlen. Eine Zahl nach dem "%" legt die Anzahl der Ausgabe-Zeichen fest, ein zusätzlich vorangestelltes Zeichen "0" oder " " füllt damit bis zur gewünschten Länge. Alle anderen Zeichen im Format-String werden direkt wiedergegeben. printf() mit Option '%X' wird nur für die Ausgabe einzelner Hex-Zahlen verwendet. Spezialfälle: Zur Hex-Ausgabe von Strings kann man die Funktion unpack() (s.o.) verwenden. Die gleiche Funktion eignet sich auch zur Ausgabe von Binär-Codes, hier angewendet auf ein einzelnes Byte mit dem Dezimalwert 10. ♦ Details dazu in der ausführlichen Perl-Referenz unter perlfunc . |
Beispiele:
$i=123.456;
printf("%d",$i); # 123 $s=sprintf("%d",$i); print "i=$s"; # i=123 printf("%05d",$i); # 00123 printf("%f",$i); # 123.456 printf("% 7.2f",$i); # 123.46 printf("%X",$i); # 7B printf("0x%X",$i); # 0x7B $s="ABC\n"; print uc(unpack("H*",$s)); # 4142430A
print unpack("B*","\x0A");
# 00001010
|
Dezimal ↔ Hex StringDas Beispiel rechts zeigt eine der Möglichkeiten für diese häufig gebrauchte Umwandlung.Zum Test wird eine (dezimale) Zufallszahl erzeugt. • Die Standard-Funktion sprintf() wird zur Codierung eines Hex-Strings verwendet (hier mit 4 Ziffern). • Im zweiten Teil wird der Hex String mit einem vorangestellten 0x in eine für Perl verwendbare Form gebracht. Der Hex String wird mit hex() oder eval() interpretiert (hex() kann auch auf das Prefix 0x verzichten). • Wenn negative Werte im → 2er-Komplement codiert sind, dann müssen sie nach der Umwandlung in eine Dezimalzahl umgeformt werden. Dazu wird das höchstwertige Bit (Hex-Ziffer 0x8) getestet. Das Beispiel rechts ergibt dezimal(0xFFFFFF80)=-128
|
Dezimalzahl → Hex String
my $x = int(rand(100));
Hex String → Dezimalzahlmy $y = sprintf("%04X",$x); print "hex($x)=$y\n";
my $z = "0x".$y;
Negative Werte im 2er-Komplement:
my $r = hex($z); # eval("\$r=$z;");
print "dezimal($z)=$r\n";
$z = "0xFFFFFF80";
$r = hex($z); if($r & 0x80000000) {$r=$r-0xFFFFFFFF-1;} print "dezimal($z)=$r\n"; |
|
Typ-Umwandlung
Perl kennt keine "Typbindung", d.h. die Daten werden intern jeweils
in jenen Typ (String, Ganze Zahl, Gleitkomma-Zahl) umgewandelt, der im gegebenen
Zusammenhang 'richtig' erscheint. In manchen Fällen ist es notwendig, einen
bestimmten Typ zu erzwingen: Benutzen sie in diesem Fall Operatoren oder Funktionen.
|
$a="12345";
// Ganze Zahl (integer)
$b=$a+0;// Gleitkomma-Zahl (double)
$c=$b+0.0;
// String
$d=$c."";
|
Zahlensysteme in PHP |
|
Quelltext:● Zahlen mit führender Ziffer '0' werden als Octalzahl (Basis 8) interpretiert.● Zahlen mit führender Dezimalziffer > '0' werden als Dezimalzahl (Basis 10) interpretiert. ● Zahlen mit führenden Zeichen '0x' werden als Hexadezimalzahl (Basis 16) interpretiert. |
Im Zweifel addiert man die Zahl 0 zu einer Variablen: Sie wird dann immer als Zahl interpretiert: $zal = $_GET['xyz']+0;
|
Codierung und Decodierung:• Die Funktion pack() führt nach ↑ Perl-Muster alle anfallenden Umwandlungs-Aufgaben durch.Je nach Version sind evtl. manche Optionen nicht verfügbar. • Funktion unpack() arbeitet auf PHP etwas anders als in Perl und liefert ein → Array. ♦ Details dazu in der offiziellen PHP-Referenz (de): pack, unpack. |
Codierung einer ganzen Zahl in Binär-Code:
$s = pack('L',123456);
Die Variable $s enthält danach 4
Byte: 40 E2 01 00 Decodierung von Binär-Code mit der oben erzeugten 4-Byte-Variablen $s $na = unpack("L",$s);
Das Array $na enthält danach 1 Element mit dem
Wert = 12345
|
Formatierung eines Zahlen-Strings:Die Funktionen printf() und sprintf() funktionieren nach ↑ Perl-Muster.♦ Details zur Funktion sprintf |
Beispiel: Ausgabe als Hexadezimal-Zahl:
print sprintf('#%04X',171);
ergibt #00AB
|
Umwandlungs-FunktionenPHP bietet einige Funktionen zur Umwandlung von/in verschiedene Zahlensysteme.base_convert (numstring, from, to)
übersetzt Zahlen-Strings beliebiger Zahlensysteme, z.B.
$binstr = base_convert('A1', 16, 2);
übersetzt die dezimale Zahl 161.0 von Hexadezimal (16) nach Binär (2)
und ergibt
$binstr = '10100001';
Diese Funktion kann auch exotische Zahlensysteme übersetzen, z.B. mit
Basis 3, 4, 5,, ...36intval (numstring, from)
übersetzt Strings zu ganzen dezimalen Zahlenwerten, z.B.
$decnum = intval('A1', 16);
übersetzt einen hexadezimalen Zahlen-String in dem Wert
$decnum = 161;
Vorsicht: Gleitkomma-Werte werden abgeschnitten, das Verhalten beim
Überschreiten der Typ-Grenzen (overflow, underflow) kann je nach
Betriebssystem variieren.
|
Diese Funktionen dienen zur Umwandlung von Zahlen-Strings verschiedener Systeme. Dezimale Werte können auch als Zahlenwerte (Ohne "") angegeben werden: bindec, decbin, dechex, decoct, hexdec, octdec
Beispiele:
decbin(12) = '1100'
decoct(12) = '14' dechex(12) = 'c' bindec('1101') = 13 octdec('15') = 13 hexdec('D') = 13 ♦ Details in der offiziellen PHP-Referenz (de): base_convert, bindec, decbin, hexdec, dechex, octdec, decoct |
Zahlensysteme in SQL |
|
| SQL ist zwar ein Standard, daneben existieren jedoch zahlreiche SQL-Dialekte, abhängig von Datenbank-Hersteller und Version. Auch vom SQL-Standard gibt es mehrere Versionen. |
Die Angaben müssen daher sehr vorsichtig interpretiert und mit der
eigenen Datenbank getestet werden. Als Richtwert gelten die Angaben für MySQL Version 6 |
DezimalzahlenGleitkomma-Zahlen werden immer mit Komma-Punkt angegeben.Besonders kleine oder große Werte werden in Exponential-Schreibweise angegeben. |
Beispiel: SELECT 123.456, 6.023e+23;
|
Hexadezimale Zahlenwerden wie in ODBC mit führendem 0x und einer geraden (!) Anzahl hexadezimaler Stellen angegeben. Ohne weitere Angaben werden hexadezimale Werte immer als Strings (!) interpretiert.• Addition einer Zahl (Beispiel rechts) erzwingt die Verwendung als Zahl. • Die Funktion CAST() garantiert die Verwendung der angegebenen Type |
Beispiel: Formulierung der Zahl 246.0 dezimal:
SELECT 0xF6+0;
SELECT CAST(0xF6 AS UNSIGNED); |
Hexadezimale Strings (Zeichenketten)werden in dieser Form angegeben: x'HH' oder X'hhhh'Sowohl das führende X als auch die hexadezimalen Ziffern können als Groß- oder Kleinbuchstaben verwendet werden. Es ist nur eine gerade Anzahl hexadezimaler Ziffern erlaubt. Je 2 Hex-Ziffern werden als Zeichen interpretiert. |
Beispiel: Formulierung des Strings SQL als Hex-String: SELECT x'53514C';
♦ Details Details zum Thema Zeichen-Code |
Ausgabe hexadezimaler StringsZur Ausgabe wird die Funktion HEX() verwendet. |
Beispiel:
SELECT HEX('SQL');
ergibt 53514C
|
Binäre Zahlenwerden mit führendem b'BB' oder 0b'BB' angegeben. Ohne weitere Angaben werden die Daten als Strings interpretiert.Addition von 0 oder die Funktion CAST() erzwingen die Verwendung als Zahl. Zur Ausgabe wird die Funktion BIN() verwendet. |
Beispiel: Formulierung der Zahl 12 dezimal:
SELECT 0b'01100'+0;
Ausgabe:
SELECT CAST(b'1100' AS UNSIGNED); SELECT 12,BIN(12);
ergibt 12 1100
|
Octale ZahlenZur Ausgabe wird die Funktion OCT() verwendet. |
Ausgabe: SELECT 12,OCT(12);
ergibt 12 14
|
Zahlensysteme in VBA |
|
Quelltext:● Zahlen ohne weitere Angaben werden als Dezimalzahl (Basis 10) interpretiert, auch solche mit führenden Nullen.● Zahlen mit führenden Zeichen '&H' werden als Hexadezimalzahlen (Basis 16) interpretiert. |
Beispiele:
x = 11 ' 11.
x = &H11 ' 17. |
Codierung von Zahlen-Strings:Funktion Hex() wandelt eine Zahl in einen Hexadezimal-String um.Funktion Oct() wandelt eine Zahl in einen Octal-String um. |
s = Hex(123)
' 7B
s = Oct(123)
' 173
|
| Die Standard-Funktion Val() kann man zur Decodierung von Hex-Strings verwenden. | dec = Val("&H" & hexstring) |
|
Muster einer Funktion dec_to_bin() zur Umwandlung einer
positiven ganzen Zahl in einen Binär-String (Codierung, ohne Gewähr). Für den Zahlenwert decnumber=0 wird der Algorithmus umgangen und der String bin=0 eingesetzt. Zuerst wird die größte benötigte Binärstelle istart ermittelt. Dann werden - beginnend mit istart - die binären Ziffern in einer Schleife durchlaufen, von der höchstwertigen zur niedrigst-wertigen. Variable j ist der Stellenwert, Variable b die Binärziffer. Damit ist die einfache Berechnung abgeschlossen. Optional (Quelltext in grün) kann man den erzeugten String in eine bestimmte Länge umwandeln. Die Anzahl Binärstellen wird mit digits optional vorgegeben. Wenn digits nicht angegeben wird, dann wird der Binärstring so zurückgegeben wie berechnet. Wenn digits > Anzahl der berechneten Binärstellen, dann wird der String mit führenden Nullen ergänzt. Wenn digits < Anzahl der berechneten Binärstellen, dann wird ein Fehlerwert (hier Fehler Nr. 1000) zurückgegeben. |
Function dec_to_bin(decnumber As Double optional digits as Integer=0) As String
Dim i, j, b, istart As Integer Dim d As Long Dim bin As String
d = CLng(decnumber)
If (d = 0) Then bin = "0"
Else
istart = Int(Log(d) / Log(2))
End If
For i = istart To 0 Step -1
j = 2 ^ i
Next
b = d \ j If b > 0 Then bin = bin & "1"
Else
bin = bin & "0"
End Ifd = d - b * j
If digits > 0 Then
dec_to_bin = bin
If Len(bin) > digits Then
End If
Err.Raise 1000
Else
bin = String(digits,"0") & bin
End If
bin = Right(bin, digits) |
|
Muster einer Funktion bin_to_dec() zur Umwandlung eines
Binärstrings (Binärzahl als Zeichenkette) in eine Dezimalzahl
(Decodierung, ohne Gewähr). In der Schleife wird je eine Ziffer bd aus dem String entnommen und in eine Zahl n umgewandelt. Die Dezimalzahl dec wird schrittweise aufgebaut, indem ihr jeweiliger Wert mit 2 multipliziert und die Binärziffer addiert wird. Jedes andere Zeichen als "0" oder "1" bewirkt die Rückgabe eines Fehlerwerts (hier Fehler Nr. 1000) |
Function bin_to_dec(binstring As String) As Long
Dim i, n As Integer Dim dec As Long Dim bd, s As String
s = binstring
End Function
dec = 0 For i = 1 To Len(s)
bd = Mid(s, i, 1)
NextIf (bd = "0" Or bd = "1") Then n = Val(bd)
Else
Err.Raise 1000
End Ifdec = 2 * dec + n bin_to_dec = dec |