Zahlensysteme, Byte-Größen und die Einheiten, über die gestritten wird

Wie Hex auf Bits abgebildet wird, warum eine 1-TB-Platte als 931 GB erscheint, was 0,1 plus 0,2 tatsächlich ergibt und wie Rundung, Prozentangaben und lokale Formatierung eine Zahl still und leise verändern.

Eine geschriebene Zahl trägt zwei Dinge: einen Wert und eine Reihe von Annahmen darüber, wie sie zu lesen ist. 0xFF, 255, 0o377 und 11111111 sind eine Größe in vier Schreibweisen. Ein Terabyte und ein Tebibyte unterscheiden sich um zehn Prozent. 1,234 ist in London ungefähr tausend und in Berlin ungefähr eins. Die meisten Zahlenfehler kommen von den Annahmen und nicht von der Rechnung.

Binär, oktal, dezimal und hexadezimal

Jedes Stellenwertsystem funktioniert gleich. Jede Stelle ist die Basis mal die Stelle zu ihrer Rechten wert, und die Ziffern laufen von null bis Basis minus eins. Basis 16 braucht sechs zusätzliche Ziffern und borgt sich deshalb A bis F für zehn bis fünfzehn.

Hexadezimal wird für Bytes und Farben verwendet, weil 16 gleich 2 hoch 4 ist; eine Hexziffer sind also genau vier Bit und ein Byte genau zwei Hexziffern, ohne Übertrag dazwischen.

0 0000   4 0100   8 1000   C 1100
1 0001   5 0101   9 1001   D 1101
2 0010   6 0110   A 1010   E 1110
3 0011   7 0111   B 1011   F 1111

Diese Tabelle ist die gesamte Umrechnung. Von hex nach binär ersetzt du jede Ziffer durch ihre vier Bit: 0x2F wird zu 0010 1111. Zurück gruppierst du die Bits von rechts zu Vierergruppen, füllst links mit Nullen auf und liest jede Gruppe in der Tabelle ab.

Für dezimal nimmst du die Stellenwerte. 0x2F ist 2 x 16 + 15, also 47. In die andere Richtung teilst du wiederholt durch 16 und liest die Reste von unten nach oben:

200 / 16 = 12 remainder 8   -> 8
 12 / 16 =  0 remainder 12  -> C
200 decimal = 0xC8

Oktal packt drei Bit in eine Ziffer, deshalb werden Unix-Rechte als 755 geschrieben: Jede Ziffer ist ein rwx-Tripel, 7 ist 111 und 5 ist 101. Eine CSS-Farbe wie #FF8800 sind drei Bytes, eines je Kanal, jedes von 0 bis 255, und die dreistellige Kurzform #F80 wird durch Verdoppeln jeder Ziffer erweitert und nicht durch Auffüllen mit Nullen. Der Number Base Converter deckt alle vier Basen auf einmal ab.

Zweierkomplement, und woher die Wertebereiche kommen

Ein Byte fasst 256 verschiedene Muster. Vorzeichenlos gelesen sind das 0 bis 255. Mit Vorzeichen gelesen markiert das oberste Bit die negative Hälfte, und ein negativer Wert ist sein Muster minus 256. Dieses Verfahren ist das Zweierkomplement, gewählt, weil die gewöhnliche binäre Addition dann für Werte mit und ohne Vorzeichen identisch funktioniert.

Um eine Zahl zu negieren, invertierst du jedes Bit und addierst eins. Der Bereich ist unsymmetrisch, weil die Null einen der 128 Plätze in der nicht negativen Hälfte belegt, ein Byte mit Vorzeichen läuft also von -128 bis 127. Eins zum oberen Ende des Bereichs zu addieren springt an das untere:

  0111 1111    127
+ 0000 0001      1
= 1000 0000   -128

In den meisten Sprachen wird nichts gemeldet; der Wert taucht einfach auf der anderen Seite des Bereichs auf. Derselbe Umschlag bei 32 Bit ist das Jahr-2038-Problem, bei dem ein Unix-Zeitstempel mit Vorzeichen und 32 Bit bei 2.147.483.647 Sekunden ausläuft. 16 Bit ohne Vorzeichen ergeben 0 bis 65.535, und genau deshalb hören TCP-Portnummern dort auf und deshalb zieht der Random Port Generator aus diesem Bereich und meidet dabei die reservierten Ports unter 1024.

Kilobyte, Kibibyte und die fehlenden Gigabyte

Speicherhersteller zählen in Zehnerpotenzen. Betriebssysteme haben historisch in Zweierpotenzen gezählt und das Ergebnis mit dem dezimalen Präfix beschriftet, und genau da beginnt der Streit. Die binären Präfixe (KiB, MiB, GiB) gibt es, um die Mehrdeutigkeit zu beseitigen.

ZehnerpotenzDezimalwertBinärpräfixBinärwertAbstand
kB, 10^31.000KiB, 2^101.0242,4 %
MB, 10^61.000.000MiB, 2^201.048.5764,9 %
GB, 10^91.000.000.000GiB, 2^301.073.741.8247,4 %
TB, 10^121.000.000.000.000TiB, 2^401.099.511.627.77610,0 %
PB, 10^1510^15PiB, 2^501.125.899.906.842.62412,6 %

Eine 1-TB-Platte fasst im Verkaufszustand 10^12 Bytes. Teile das durch 2^30, und du erhältst 931,32; Windows meldet also etwa 931 GB und verwendet damit die dezimale Beschriftung für eine binäre Menge. Es fehlt nichts; dieselben Bytes werden nur durch eine andere Zahl geteilt. macOS und die meisten Linux-Werkzeuge melden inzwischen dezimale GB, was zur Verpackung passt. Speichergrößen sind tatsächlich binär, 16 GB RAM sind also wirklich 16 GiB.

Netzwerkgeschwindigkeiten werden in Bit gezählt, nicht in Byte, und immer dezimal. Eine Leitung mit 100 Mbps trägt 100.000.000 Bit pro Sekunde, das sind 12,5 MB pro Sekunde vor Overhead. Der Protokoll-Overhead frisst einige Prozent, 11 bis 12 MB pro Sekunde sind also die realistische Obergrenze. Eine beworbene Megabit-Zahl durch acht zu teilen ist die schnelle Probe, und der Unit Converter deckt die Speichereinheiten ab.

Gleitkomma, und warum Geld kein Float ist

Binäre Brüche können nur Summen aus Hälften, Vierteln, Achteln und so weiter darstellen. Ein Zehntel hat keine exakte binäre Form, so wie ein Drittel keine exakte dezimale Form hat; 0.1 als IEEE-754-Double gespeichert ist also etwas mehr als ein Zehntel. Addiere zwei solche Näherungen, und der Fehler tritt zutage:

0.1 + 0.2 = 0.30000000000000004

Ein Double hat 53 Bit Mantisse. Damit ist jede ganze Zahl bis 2^53 (9.007.199.254.740.992) exakt darstellbar, ebenso jeder Bruch, dessen Nenner eine Zweierpotenz ist. Oberhalb von 2^53 wird der Abstand zwischen darstellbaren Werten 2, 2^53 + 1 ist also gleich 2^53. Deshalb sollten 64-Bit-Datenbankidentifier, die durch JSON geschickt werden, als Zeichenketten reisen: JavaScript-Zahlen sind Doubles, und eine 19-stellige ID verliert stillschweigend ihre letzten Ziffern.

Für Geld speicherst du ganzzahlige Untereinheiten (Cent) oder nutzt einen Dezimaltyp, der zur Basis zehn rechnet. Vergleiche Gleitkommazahlen nie auf Gleichheit; vergleiche die Differenz gegen eine kleine Toleranz. Der Expression Calculator rechnet ebenfalls in Doubles und erbt dieselben Grenzen.

Runden, und zweimal runden

Half up rundet einen Gleichstand von der Null weg. Half even, auch Bankiersrundung genannt, schickt einen Gleichstand zur nächstgelegenen geraden Ziffer und beseitigt damit die Aufwärtsverzerrung, die half up über eine lange Zahlenspalte hinweg einbringt. Es ist der Standard von IEEE 754 und die Regel in mehreren Rechnungslegungsstandards.

WertHalf upHalf even
0,510
1,522
2,532
3,544
-0,5-10

Runde einmal, vom ursprünglichen Wert aus. 2,4449 auf drei Nachkommastellen gerundet ergibt 2,445, und das auf zwei gerundet ergibt 2,45, während das Original direkt auf zwei gerundet 2,44 ergibt. Verkettetes Runden über Zwischenspalten hinweg ist eine häufige Ursache für Summen, die um einen Cent danebenliegen. Eine verwandte Überraschung: 2,675 wird in den meisten Sprachen zu 2,67 gerundet, weil das gespeicherte Double 2,67499999999999982 ist.

Prozent und Prozentpunkt

Ein Satz, der von 4 % auf 5 % steigt, ist um einen Prozentpunkt gestiegen oder relativ um 25 %. Beides ist richtig, und die Einheit muss dazugesagt werden.

Prozentuale Änderungen heben sich nicht auf. Ein Rückgang um 50 % gefolgt von einem Anstieg um 50 % lässt 75 übrig, nicht 100, weil der zweite Prozentsatz von einer kleineren Basis genommen wird. Einen Rückgang um p auszugleichen erfordert einen Anstieg um p / (1 - p), ein Rückgang um 50 % braucht also 100 % und ein Rückgang um 80 % braucht 400 %. Aufeinanderfolgende Änderungen multiplizieren sich und bilden eine geometrische Folge statt einer Summe, und genau dieses Wachstum bildet das Werkzeug Number Sequence ab.

Die Änderung von einem alten zu einem neuen Wert ist (new - old) / old x 100, und genau das meldet der Percentage Calculator als Differenz. 20 % Mehrwertsteuer herauszurechnen heißt durch 1,2 zu teilen und nicht 20 % abzuziehen. Prozentsätze über verschieden große Gruppen zu mitteln ergibt die falsche Gesamtzahl, sofern der Durchschnitt nicht gewichtet wird, und dass Sum and Average einen Median neben dem Mittelwert zeigt, macht die Schiefe sichtbar.

Zahlen, die für eine Locale formatiert sind

Formatierung ist eine Entscheidung über die Darstellung und ohne Kenntnis der Locale nicht umkehrbar. 1.234 ist im Vereinigten Königreich etwas mehr als eins und in Deutschland eintausend. 1,234 ist genau umgekehrt. Manche Locales gruppieren stattdessen mit einem Leerzeichen oder einem Apostroph.

Locale1234567.89
en-GB, en-US1,234,567.89
de-DE1.234.567,89
fr-FR1 234 567,89
de-CH1'234'567.89
en-IN12,34,567.89

Die indische Gruppierung setzt das erste Trennzeichen nach drei Ziffern und danach alle zwei Ziffern, was Lakh und Crore ergibt statt Tausend und Million. Eine formatierte Zeichenkette zurück in eine Zahl zu parsen ist genau deshalb verlustbehaftet; speichere und übertrage Werte also unformatiert mit einem Punkt als Dezimaltrennzeichen und formatiere erst an der Stelle der Anzeige. Wo eine Zahl für einen Leser eindeutig sein muss, ist es auf Schecks und in Verträgen üblich, sie mit Number to Words auszuschreiben. Römische Zahlen stehen außerhalb von all dem: ohne Stellenwert und ohne Null verarbeitet der Roman Numeral Converter eine Strichliste und kein Zahlensystem.