Left shift operation
Verfasst: 11.08.2011, 09:13
Hallo zusammen,
ich implementiere aktuell einen UnitTest für meine floatToFixedPoint Umrechnung die ich im Pixelprocessing benötige.Dabei bin ich auf ein Verhalten gestoßen, dass ich mir nicht so ganz erklären kann. Für gültige Farbwerte [0.0f..1.0f] führe ich einen einfachen links shift um n bits eines float Wertes durch:
unsigned int fixed = fValue * (1<<nbits);
Nichts weltbewegendes. Klappt auch für alle 8,16,24 bit werte. Ich weiß, laut ISO C99 Spezifikation ist der Grenzwert 31, da er noch keinen Overflow erzeugt. Dennoch passen meine Tests für diesen Wert nicht und ich habe z.T. "marginale Abweichungen" in den Berechnungen.
Ich habe mal den Wert 0.2835f genommen und für 8,16,24 bits berechnet. Passt. Nehme ich den gleichen Wert für 31bit, dann passt es nicht mehr. Hier erhalte ich einen Wert von 608811584 und erwarte einen Wert von 608811614 ... Die Abweichungen kann ich mir noch mit der zunehmenden Genauigkeit erklären und der Ursache, dass der float nicht exakt 0.2835 ist sondern laut debugger als 0.283499986 behandelt wird. Wie ich diese Ungenauigkeit im Test abfange ist mir aktuell auch noch nicht klar, da ich hier keine floats im Resultat prüfe sondern unsigned ints und so kein Delta berücksichtigen kann ...
Mir ist auch aufgefallen dass ich nur bei 31 bits ein Problem mit dem shift operator habe. Die Anweisung wie oben dargestellt
unsigned int fixed = fValue * (1<<nbits);
Klappt nicht. Hier muß ich die Anweisung umbauen zu:
unsigned int shift = (1<<nbits);
unsigned int fixed = fValue*shift;
Um ein gültiges Resultat zu erhalten, ansonsten ist das Resultat falsch und ich erhalte statt der erwarteten 608811614 einen Wert
von 3686155712 ...
Als Vergleich habe ich zusätzlich mal mit 30bit gerechnet, hier funktioniert zwar noch der eigentliche shift Operator korrekt, aber ich
habe ebenfalls eine Abweichung im Ergebnis und erhalte 304405792 anstelle von 304405807.
Aber das der Shift Operator bei 31bits nicht mehr korrekt greift ist mir ein Rätsel.
Habe ich irgend etwas übersehen oder falsch verstanden?
Gruß
Hellhound
ich implementiere aktuell einen UnitTest für meine floatToFixedPoint Umrechnung die ich im Pixelprocessing benötige.Dabei bin ich auf ein Verhalten gestoßen, dass ich mir nicht so ganz erklären kann. Für gültige Farbwerte [0.0f..1.0f] führe ich einen einfachen links shift um n bits eines float Wertes durch:
unsigned int fixed = fValue * (1<<nbits);
Nichts weltbewegendes. Klappt auch für alle 8,16,24 bit werte. Ich weiß, laut ISO C99 Spezifikation ist der Grenzwert 31, da er noch keinen Overflow erzeugt. Dennoch passen meine Tests für diesen Wert nicht und ich habe z.T. "marginale Abweichungen" in den Berechnungen.
Ich habe mal den Wert 0.2835f genommen und für 8,16,24 bits berechnet. Passt. Nehme ich den gleichen Wert für 31bit, dann passt es nicht mehr. Hier erhalte ich einen Wert von 608811584 und erwarte einen Wert von 608811614 ... Die Abweichungen kann ich mir noch mit der zunehmenden Genauigkeit erklären und der Ursache, dass der float nicht exakt 0.2835 ist sondern laut debugger als 0.283499986 behandelt wird. Wie ich diese Ungenauigkeit im Test abfange ist mir aktuell auch noch nicht klar, da ich hier keine floats im Resultat prüfe sondern unsigned ints und so kein Delta berücksichtigen kann ...
Mir ist auch aufgefallen dass ich nur bei 31 bits ein Problem mit dem shift operator habe. Die Anweisung wie oben dargestellt
unsigned int fixed = fValue * (1<<nbits);
Klappt nicht. Hier muß ich die Anweisung umbauen zu:
unsigned int shift = (1<<nbits);
unsigned int fixed = fValue*shift;
Um ein gültiges Resultat zu erhalten, ansonsten ist das Resultat falsch und ich erhalte statt der erwarteten 608811614 einen Wert
von 3686155712 ...
Als Vergleich habe ich zusätzlich mal mit 30bit gerechnet, hier funktioniert zwar noch der eigentliche shift Operator korrekt, aber ich
habe ebenfalls eine Abweichung im Ergebnis und erhalte 304405792 anstelle von 304405807.
Aber das der Shift Operator bei 31bits nicht mehr korrekt greift ist mir ein Rätsel.
Habe ich irgend etwas übersehen oder falsch verstanden?
Gruß
Hellhound