Zum 3DCenter Forum
Inhalt




Das Floating-Point-Format im Detail

Teil 1 von 3 / 1. März 2004 / von aths / Seite 2 von 13


   Das Zweierkomplement - Für Zahlen kleiner Null

Zurück zu den Ganzzahlen, die wir in einem Byte kodieren. Um negative Werte darzustellen, nutzt man ein Bit als Vorzeichen (englisch: Sign). Um die Übersicht zu erleichtern, legen wir fest, das Vorzeichen-Bit rot zu schreiben, und die eigentliche Zahl in Blau. Betrachten wir das Bitmuster für die 5: 0000'0101. Das erste Bit soll das Vorzeichen sein: 0 entspricht + und 1 steht für -. Wie wird die -5 dargestellt? Intuitiv würde man auf diese Darstellung tippen: 1000'0101. Doch das ist falsch. Mit einem schnöden Vorzeichenbit würde man die Null zwei mal kodieren, einmal als "+0" mit 0000'0000 und einmal als "-0" mit 1000'0000. In der Praxis tut man das nicht, sondern verwendet das Zweierkomplement, um eine Zahl zu negieren.

Dazu wird zunächst jedes einzelne Bit negiert. Aus 0 wird 1 und aus 1 wird 0. Die 5, gespeichert als 0000'0101 wird zur 1111'1010. Auf dieses Ergebnis wird noch 1 addiert. Man gelangt dann zu 1111'1011. Das ist die Kodierung von -5 im Zahlenformat signed char. Die größte positive darstellbare Zahl ist nun 0111'1111, also 127.

Eine häufige Fragestellung ist, wie denn -1 aussieht. Nun, -1 heißt im Zweierkomplement immer, dass das Bitmuster über die gesamte Breite auf 1 gesetzt ist. Beim "Byte mit Vorzeichen" wird -1 also durch 1111'1111 repräsentiert.

Auf der Plus-Seite kommt man bis 127. Wie weit reicht die Darstellung auf der Negativ-Seite? Bis -128! Wenn das Vorzeichen-Bit 1 ist, und der Rest 0, steht dieser Code für -128. Wer möchte, kann das nachrechnen. Dieses "Ungleichgewicht", dass man im negativen Bereich etwas weiter kommt, besteht beim Zweierkomplement immer. Welche Auswirkungen das hat, werden wir noch sehen.

Wenn man die negative Darstellung von Zahlen häufiger berechnen möchte, wird der Weg über das Zweierkomplement etwas mühselig. Die Berechnung lässt sich vereinfachen: Ohne Vorzeichen ist 255 die größte darstellbare Zahl. Wir addieren die 1 sofort und haben somit die Zahl 256. Unsere -5 entspricht nun ganz einfach 256 -5, also 251. Die 251 hat das Bitmuster 1111'1011. Genau so sieht die -5 aus.

Dass man das Zweierkomplement zur Darstellung von negativen Zahlen verwendet, hat sein Gründe in der Rechenlogik. Beispielsweise lässt sich ADD und SUB vereinfachen, so dass das Vorzeichen-Bit gar nicht als Vorzeichen ausgewertet werden muss, sondern wie eine binäre Stelle mitverrechnet werden kann. Klingt unglaublich? Probe auf's Exempel:


100 - 105 = -5

Die Subtraktion wird "ganz normal" durchgeführt. Uns interessiert jetzt nicht die Schaltungstechnik, wie ein Addierer mit etwas Zusatz-Verdrahtung und ein klein wenig Extra-Logik zu einem umschaltbaren ADD/SUB umgebaut werden kann, sondern nur, "wie man das rechnet". Von rechts nach links: 0 - 1 geht nicht, also rechnen wir binär 10 - 1 = 1 (dezimal 2 - 1 = 1) und die Entlehnung von 1 nehmen wir in die nächste Stelle (das ist übrigens das "Carry-Bit", was dann bis an das Ende des Registers geschoben wird). Auf der nächsten Position haben wir 0 - 1 (die 1 kommt aus der Entlehnung) und müssen wieder 10 - 1 rechnen, und eine 1 entlehnen. Die nächste Stelle ergibt sich aus 1 -1 = 0, wobei der Minuend in der oberen Zahl steht, und sich der Subtrahend aus der Entlehnung ergibt ... Das führt man fort bis zur Stelle ganz links fort und bekommt dann dieses Ergebnis: 1111'1011 - das Bitmuster für die -5.

Das ist nur dank dem Zweierkomplement so einfach zu rechnen! Doch nun wollen es mit damit erst mal gut sein lassen und die Frage klären: Wie, oder genauer, womit rechnen GeForce1 bis GeForce4?


   FX9 - Grundlage der Register Combiner

Fixpoint9, wofür abgekürzt FX9 steht, funktioniert folgendermaßen: Wir nehmen FX8, und erweitern das Format um 1 Bit. Damit hat man 8 volle Bits für die Zahl, und zusätzlich das Vorzeichenbit. Das Bitmuster für 1,0 in FX9 ist 0'1111'1111. Würden man diese FX9-Zahl als Int9 interpretieren, hätten wir 255. -1 wird als "-255" gespeichert, demzufolge als 1'0000'0001. Bekannter Nebeneffekt: Mit 1'0000'0000 wird, als Int9 interpretiert, "-256" kodiert, was umgerechnet für -1,003 steht (genauer gesagt, für -256 / 255.) Im Negativen kommt man wie gewohnt ein klein wenig weiter, insgesamt steht der Bereich von -1,003 bis +1,000 zur Verfügung.

Das ist mehr als ein vorzeichenbehaftetes FX8 bietet, dieses erlaubt nur Werte von -1,0 bis 0,992. Dieses FX mit Vorzeichen spielt bei bestimmten Texturen eine Rolle, und ist ansonsten eigentlich nicht anzutreffen. FX9 kann auch 1,0 noch darstellen. Leider sind die Zahlenwerte 0,5 und -0,5 nicht exakt speicherbar (was wiederum mit dem vorzeichenbehaftetem FX8 möglich ist), aber -1, sowie 0 und 1 können mit FX9 exakt kodiert werden.

FX9 hat weitere Vorteile: Textur-Werte können direkt übernommen werden, da die Bitmuster kompatibel sind. Vorne muss man lediglich eine 0 als Sign-Bit anfügen. Ebenso können positive FX9-Werte direkt so, wie sie sind, nach Abschneiden des Vorzeichens in den Framebuffer gelangen, negative Werte werden in eine Null umgewandelt. Die Rechenwerke setzen ganz auf die bewährtem, einfach zu realisierende Technik mit dem Zweierkomplement. Wie bereits bei FX8 erwähnt, müssen die MUL-Einheiten (für Multiplikationen) nach der normalen Multiplikation das Ergebnis nicht nur "richtig hinschieben", sondern es auch gegebenenfalls um ein Bit korrigieren.

Obwohl FX9 ja "Fixpoint9" heißt, kann man nicht so richtig in einen Vorkomma- und einen Nachkomma-Teil trennen. Die 8-bittige Darstellung für den Betrag ist nicht als Nachkomma-Anteil zu verstehen, sonst wäre die größte Zahl "binär 0,11111111" = "dezimal 0,996".

Es soll nicht verschwiegen werden, wie man binäre Kommastellen in das Dezimal-System umrechnet. Im Vorkomma-Bereich stehen die Bit-Positionen für gewisse Zweierpotenzen. Die Stellen von rechts nach links gezählt, verdoppelt sich die Wertigkeit jeweils. Das ist bei einem gedachten Nachkomma-Teil vergleichbar, "nur anders herum": Von links nach rechts halbieren sich die Wertigkeiten für die binären Stellen. Das entspricht also 0.5, 0.25, 0.125 und so weiter. Da alle acht Nachkomma-Bits gesetzt sind, werden alle Zahlen addiert, was ungefähr zur 0,996 führt. Wie gesagt, darf man sich bei FX9 hinter dem Vorzeichenbit kein Komma denken. Eigentlich gibt es bei FX9, genau wie bei FX8 gar kein Komma.

GeForce 1, 2, 3 und 4 verrechnen Farben immer im FX9-Format. Für Textur-Filterung werden die FX8-Werte zunächst auf FX10 "aufgebläht", um Rundungsfehler zu minimieren. Das fertig gefilterte Sample wird dann auf FX8 gerundet. Für Rechnungen im Register Combiner wird der Farbe noch ein Vorzeichen-Bit spendiert, was effektiv einer Konvertierung nach FX9 entspricht. Lange Zeit war das gut genug. Immerhin unterstützen auch modernste GeForce-Karten noch Fixpoint-Formate - natürlich ein besseres als FX9.






Kommentare, Meinungen, Kritiken können ins Forum geschrieben werden - Registrierung ist nicht notwendig Zurück / Back Weiter / Next

Shortcuts
nach oben