Pfad: Home => AVR-Überblick => Programmiertechniken => Fließkommazahlen    (This page in English: Flag EN) Logo

Programmiertechnik für Anfänger in AVR Assemblersprache

Fließkommazahlenberechnungen in Assemblersprache

Fließkommazahlen, bitte schön, wenn es unbedigt sein muss

Wer sich das Leben schwerer machen möchte als unbedingt sein muss: es gibt neben Ganzzahlen, vorzeichenbehafteten Ganzahlen und Festkomma-Zahlen auch Fließkommazahlen. Was in Hochsprachen so einfach daherkommt wie 1,234567 ist in Assembler aber ziemlich kompliziert. Und das kommt so.

Das Format von Fließkommazahlen

Binäre Fließkommazahlen bestehen aus zwei Bestandteilen:
  1. einer Mantisse, und
  2. einem Exponenten.
In der dezimalen Welt gibt die Mantisse den Zahlenbestandteil an, bei 1,234567 würde sie lauten: 1,234567E+00. Der Exponent gibt an, wie oft die Mantisse mit 10 malgenommen werden muss, in unserem Beispiel wäre das keinmal, also eine Null. Mantissen beginnen also immer mit einer Ziffer ungleich Null vor dem Komma. Ist die Zahl größer als Eins, wird sie solange durch 10 geteilt, bis sie mit irgendeiner einzelnen Ziffer anfängt. Dabei wird der Exponent immer um eins nach oben gezählt.

Umgekehrt: ist die Zahl kleiner als 1 und ist die erste Ziffer vor dem Komma Null, wird sie solange mit 10 multipliziert, bis die erste Ziffer vor dem Komma nicht mehr Null ist. Jetzt wird der Exponent abwärts gezählt, bei 0,01234567 zweimal, er wird also minus Zwei. Der Exponent muss bei solchen Zahlenwerten daher ein Vorzeichen haben, damit er negativ werden kann.

Den Vorgang, dass der Exponent so lange verschoben wird, bis die erste Ziffer vor dem Komma nicht größ oder gleich 10 und nicht Null wird, bezeichnet man als Normalisieren. Das werden wir im Folgenden und beim Umwandeln von binären Fließkommazahlen in dezimales Zahlenformat noch oft sehen.

Zahlen selbst können aber selbst auch negativ werden, wie -1,234567. Da sich durch Malnehmen und Teilen das Vorzeichen der Zahl nicht ändert, braucht auch die Mantisse ein Voreichen, wenn negative Zahlen verarbeitet werden sollen, z. B. -183°C (der Siedepunkt des Sauerstoffs). Normalisiert würde diese Zahl 1,83E+02 lauten.

16-Bit-Fliesskomma-Zahl Übertragen in die binäre Welt brauchen Fließkommazahlen also wenistens zwei Bytes: eines für die Mantisse und eines für den Exponenten. Beide haben ein Vorzeichen. Allerdings hat jedes Bit in der Mantisse und im Exponenten gänzlich unterschiedliche Bedeutungen:
  1. In der Mantisse ist jedes Bit, vom Komma oder vom höchsten her begonnen, eine um Zwei abnehmende Bedeutung. So ist das erste Bit dezimal 0,5 wert, das zweite Bit 0,25, etc. etc.
  2. Beim Exponenten ist jedes Bit, von hinten her betrachtet, immer das Doppelte des dahinterstehenden wert. Der Exponent kann daher von 0 bis 127 reichen (binär 0x00 bis 0x7F), wenn er positiv ist, und von -1 bis -128 wenn er negativ ist (0xFF für -1 und 0x80 für -128).
Da der Exponent mit der Basis Zwei hochgenommen wird (* 2 ^), ist er dezimal allerdings sehr viel mehr wert als die Mantisse. So ist 2^127 schon 1,7-mal-10-hoch-38 oder *1038 oder auch E38. Umgekehrt können negative Exponenten auch sehr kleine Zahlenwerte sein, so ist 2^-128 dezimal 2,9E-39. Mit nur acht Bit Exponent lässt sich daher schon der mächtige Zahlenbereich zwischen 2,9E-39 bis 1,7E+38 abbilden. Außer für astronomische Berechnungen kommen diese acht Bits schon gut hin.

Richtig mau sieht es aber bei der Mantisse aus: mit ihr lassen sich Zahlen nur mit zwei Dezimalziffern Genauigkeit abbilden. Schon mit 0,995 wären unsere acht Bits überfordert, da schon bei 0,992 Schluss ist.

24-Bit-Fliesskomma-Zahl Macht nix, nehmen wir halt zwei Bytes für die Mantisse. Das letzte Bit der Mantisse ist jetzt 0,0000305 wert. Damit lassen sich jetzt knapp fünf Dezimalstellen korrekt abbilden. Das ist für Genauigkeitsfanatiker noch nicht sehr befriedigend, die brauchen ein weiteres Byte (von einfacher Genauigkeit nach doppelter), und sind auch damit wahrscheinlich noch nicht zufrieden.

Deswegen wird beim Fließkomma mit jedem Mantissenbit gegeizt. Das führt dann zu allerlei verwirrenden Zusatzregeln. Da nach dem Normalisieren (das ist das Links- oder Rechtsschieben der Mantisse mit Dekrementieren bzw. Inkrementieren des Exponenten) das erste Mantissen-Bit immer eine Eins ist, kann man diese Eins auch weglassen und stattdessen in den 16 Bits ein weiteres Mantissenbit unterbringen. Mit diesem Bit-Geiz-Gefriemel verkompliziert man dann die Normen um eine weitere Variante.

Wer nicht glaubt, dass Fließkommazahlen Ressourcenfresser sind, der ziehe sich Fließkomma in Dezimalzahlen wandeln rein. Dass man für diese einfache Übung ganze 400 Zeilen Assembler-Quellcode braucht wird aber noch davon getoppt, dass diese Wandlung mehr als 4 ms Zeit braucht, in der der AVR mit nix anderem beschäftigt ist als mit Links- und Rechts-Schieben, mit Addieren und mit Bytes-Verschieben.

Ähnlich aufwändig ist die Umwandlung von Dezimalzahlen in binäre Fließkommazahlen hier. Die ist mit 527 Assembler-Quellcode-Zeilen sogar noch geringfügig aufwändiger.

Einen Vorteil haben diese Fließkomma-Orgien immerhin: sie vereinfachen das Malnehmen und Teilen zweier Zahlen. Wenn wir zwei Zahlen mit ihren Mantissen M1 und M2 und ihren Exponenten E1 und E2 (M1*2^E1, M2*2^E2) miteinander malnehmen, brauchen wir nur die Mantissen malnehmen: M = M1 * M2, die beiden Exponenten werden dann einfach addiert E = E1 + E2. Beim Dividieren werden die Mantissen geteilt und die Exponenten einfach subtrahiert.

Dafür wird das Addieren und Subtrahieren komplizierter: zuerst müssen die beiden Exponenten in Übereinstimmung gebracht werden (durch Rechtsschieben der kleineren Zahl), erst dann können beide Mantissen addiert bzw. subtrahiert werden.

Fazit:

Wer schlau ist und die Exponentenwichserei bis 1038 gar nicht braucht, bleibt bei Ganz- und Festkommazahlen (Pseudo-Fließkomma), gerne auch mit Vorzeichen, und vermeidet Fließkomma solange es irgend geht. Wer mehr Genauigkeit braucht, ist mit Ganzzahlen eh besser bedient, weil sich damit erhöhte Genauigkeit mit wenigen Bytes zusätzlich erreichen lässt, ohne dass man zu 64-Bit-Monster-Zahlen greifen muss.

Zum Seitenanfang

©2021 by http://www.avr-asm-tutorial.net