Hallo Liebe Leute, Folgendes: Ich habe arbeitsbedingt zur Zeit mit einem 32Bit µC zu tun, welcher KEINE FPU hat, weswegen an einigen Stellen aufgrund der höheren Effizienz Festkommaarithmetik auftritt. Soweit so gut, damit habe ich vom Verständnis her nicht weiter Probleme. Nun steh ich grad vor folgendem Problem, dessen Lösung sich mir seit 2 Tagen nicht erschließt und ich deshalb jetzt mal eine außenstehende Idee brauche um ggf. etwas klarer zu sehen: Die Festkommazahlen werden als Q0.31 Zahlen behandelt (1Vorzeichen+31Bit Nachkommastelle). Einige simple Funktionen wie die Multiplikation sind implementiert und liefern richtige Ergebnisse. So und nun das Problem: Für ein paar Debug ausgaben, möchte ich mir gerne einige der Ergebnise auf der Konsole anzeigen lassen. An sich kein Problem, aber Festkommazahlen sind ja für den µC nichts weiter als signed int's, welche er auch so ausgibt. Vor allem bei 32Bit werden damit die Zahlen extrem unansehnlich; Beispiel: +0,5 gelesen als Q0.31 ist in Binärdarstellung: 0|,1000000000....0 das entspricht 2^30 = 1073741824 als int gelesen .... das ist sehr wenig anschaulich. Nun wollte ich mir gerne wirklich mittels einer Konsolenausgabe (meinetwegen printf() ) anzeigen lassen, dass das 0,5 ist und nicht sonstewas ... und das bekomme ich einfach nicht hin. Vor allem bei heftigeren Zahlen, meinetwegen 0,81231236123 oder so, muss ich ja sozusagen die Nachkommabits abhängig von ihrer Wertigkeit addieren ... aber das werden dann ja wieder float Zahlen :D Vielleicht sehe ich einfach grade den Wald vor lauter Bäumen nicht mehr und es ist ganz einfach. Achso, programmiert wird in C. Grüße und frohe Ostern
Franky schrieb: > Ich habe arbeitsbedingt zur Zeit mit einem 32Bit µC zu tun Und dafür gibt es keine math.lib mit 'float' und 'double'? Das glaube ich nicht!
Natürlich gibt es die! Das ist aber nicht Sinn der Übung, ich habe eine Portierung vorzunehmen, der Code arbeitet bereits mit Festkommaarithmetik und diese ist aus Recheneffizienzgründen nicht mit floats zu behandeln, da dass ohne FPU extrem auf die Rechenleistung drückt ... Immer diese Besserwisser-Antworten hier ...
@ Franky (Gast) >Die Festkommazahlen werden als Q0.31 Zahlen behandelt (1Vorzeichen+31Bit >Nachkommastelle). Nö, das ist nicht zwingend. Siehe Festkommaarithmetik. >Nun wollte ich mir gerne wirklich mittels einer Konsolenausgabe >(meinetwegen printf() ) anzeigen lassen, dass das 0,5 ist und nicht >sonstewas ... und das bekomme ich einfach nicht hin. Wirklich? Und du machst was mit 32 Bit Prozessoren? > Vor allem bei >heftigeren Zahlen, meinetwegen 0,81231236123 oder so, muss ich ja >sozusagen die Nachkommabits abhängig von ihrer Wertigkeit addieren ... Dann tu das. >aber das werden dann ja wieder float Zahlen :D Nö. Man rechnet mit Integerdivision und Modulo. Siehe Artikel oben. >Vielleicht sehe ich einfach grade den Wald vor lauter Bäumen nicht mehr >und es ist ganz einfach. Achso, programmiert wird in C. uint32 x=123456; printf("%d.%d",x/100, x % 100); > 1234.56 Du besitzt ein C-Grundlagenbuch? Wenn nein, solltest du dir schnellstens eins kaufen.
Fuer die Anzeige darf man float verwenden. Denn die Anzeige ist nicht so haeufig. Wenn man den Display alls 100ms neu beschreibt wird es zum Ablesen schon grenzwertig schnell. Eher nur alle 300ms.
@ Franky (Gast) >Recheneffizienzgründen nicht mit floats zu behandeln, da dass ohne FPU >extrem auf die Rechenleistung drückt ... Sicher, aber für die Ausgabe auf der Konsole ist das auch ohne FPU schnel genug.
Franky schrieb: > (1Vorzeichen+31Bit Nachkommastelle) Ist das wirklich so? Gibt es in diesem Format also eine +0 und eine -0? +0 = 00000000000000000000000000000000 -0 = 10000000000000000000000000000000 Oder ist es eher wie bei einer Integerzahl, wo führende Nullen eine positive und führende Einsen eine negative Zahl anzeigen? Wie genau soll diese Anzeige sein? Reichen da evtl. schon die führenden 5 Stellen nach dem Komma?
Falk Brunner schrieb: > @ Franky (Gast) > >>Die Festkommazahlen werden als Q0.31 Zahlen behandelt (1Vorzeichen+31Bit >>Nachkommastelle). > > Nö, das ist nicht zwingend. Siehe Festkommaarithmetik. > >>Nun wollte ich mir gerne wirklich mittels einer Konsolenausgabe >>(meinetwegen printf() ) anzeigen lassen, dass das 0,5 ist und nicht >>sonstewas ... und das bekomme ich einfach nicht hin. > > Wirklich? Und du machst was mit 32 Bit Prozessoren? > >> Vor allem bei >>heftigeren Zahlen, meinetwegen 0,81231236123 oder so, muss ich ja >>sozusagen die Nachkommabits abhängig von ihrer Wertigkeit addieren ... > > Dann tu das. > >>aber das werden dann ja wieder float Zahlen :D > > Nö. Man rechnet mit Integerdivision und Modulo. Siehe Artikel oben. > >>Vielleicht sehe ich einfach grade den Wald vor lauter Bäumen nicht mehr >>und es ist ganz einfach. Achso, programmiert wird in C. > > > Du besitzt ein C-Grundlagenbuch? Wenn nein, solltest du dir schnellstens > eins kaufen. Hallo Falk, sowohl mit von dir genanntem Link als auch mit einem anderen Thema hier im Forum habe ich mich bereits befasst, wenn mir das geholfen hätte, hätte ich nichts gepostet. Also erstmal: Q0.31 ist für das Programm vereinbart definiert wie die Zahlen zu interpretieren sind, das gilt IMMER für dieses Programm, wenn es nunmal so definiert ist...reine Vereinbarungssache programmspezifisch. Verstehe deinen Kommentar dazu nicht, dass es auch andere Vereinbarungen wie meinetwegen Q1.14 etc. gibt, war nicht meine Frage. > uint32 x=123456; > > printf("%d.%d",x/100, x % 100); > >> 1234.56 Ja, das habe ich bereits gelesen in erwähntem anderen Thread. Dann mach das mal mit 2^30 und beweise mir, dass dir die Konsole 0,5 anzeigt, was sie nicht tun wird. Naja, ich merks nach den paar Posts schon, dass man sich eh wieder nur was anhören muss, wie dumm man ist... Danke für die Diskussion und trotzdem frohe Ostern
Lothar Miller schrieb: > Franky schrieb: >> (1Vorzeichen+31Bit Nachkommastelle) > Ist das wirklich so? Ja, das ist so > Gibt es in diesem Format also eine +0 und eine -0? > +0 = 00000000000000000000000000000000 > -0 = 10000000000000000000000000000000 öhhh, nein > Oder ist es eher wie bei einer Integerzahl, wo führende Nullen eine > positive und führende Einsen eine negative Zahl anzeigen? So schon eher :) > Wie genau soll diese Anzeige sein? > Reichen da evtl. schon die führenden 5 Stellen nach dem Komma? Ja, das ist erstmal nicht so wichtig.... zum funktionieren reichen mir auch ein paar Stellen.
Franky schrieb: > Naja, ich merks nach den paar Posts schon, dass man sich eh wieder nur > was anhören muss, wie dumm man ist... Danke für die Diskussion und > trotzdem frohe Ostern Nö. Aber wie schon gesagt, ist es zum Debuggen ziemlich unerheblich, ob Floating Point mal ein wenig länger dauert. (double)Zahl / (( 1U<<32)-1) das ganze als double gerechnet und ab auf die Anzeige damit.
Franky schrieb: > Ja, das ist erstmal nicht so wichtig.... zum funktionieren reichen mir > auch ein paar Stellen. Und? Wo liegt dann jetzt das Problem? Du weißt wie sich die Bits addieren. Bau dir halt eine Schleife auf, die genau das tut, was du sonst händisch machst. Wenn du mit 5 Stellen zufrieden bist, dann benutzt du halt dort auch wieder Fixkomma-Arithmetik und stellst 0.5 mittels 50000 dar. Das Nächste Bit sind dann 0.25, also 25000, das nächste 0.125, also 12500 usw. usw. Alles als Ganzzahl zusammenaddiert, noch ein 0_Komma davor und die Zahl mit führenden 0-en 5-stellig dahinter ausgegeben und schon wird dir 0b01000000000000000000000000000000 als 0.50000 ausgegeben. Das dieser 'Text' sich aus 2 Teilen zusammensetzt und da eigentlich '0.' gefolgt von 50000 steht, ist dir ja wieder wurscht. Das was du liest, entspricht der ursprünglichen Binärzahl. Vorzeichenbehandlung nicht vergessen!
Franky schrieb: > Das ist aber nicht Sinn der Übung, ich habe eine Portierung vorzunehmen, > der Code arbeitet bereits mit Festkommaarithmetik und diese ist aus > Recheneffizienzgründen nicht mit floats zu behandeln, da dass ohne FPU > extrem auf die Rechenleistung drückt ... > > Immer diese Besserwisser-Antworten hier ... Vermutlich weißt Du garnicht, welche CPU Du überhaupt verwendest. Verraten wird's jedenfalls nicht. Und Du weißt auch nicht, wie schnell diese mit 'float' rechnen können - auch ohne FPU. Dass Festkommaberechnungen signifikant schneller sein sollen als 'float' - wenn überhaupt, müßtest Du mir nachweisen. Auf dem Auge der bloßen Vermutungen bin ich nämlich blind.
@ Franky (Gast) >Also erstmal: Q0.31 ist für das Programm vereinbart definiert wie die >Zahlen zu interpretieren sind, das gilt IMMER für dieses Programm, wenn >es nunmal so definiert ist...reine Vereinbarungssache Sicher. > uint32 x=123456; > > printf("%d.%d",x/100, x % 100); > >> 1234.56 >Ja, das habe ich bereits gelesen in erwähntem anderen Thread. Dann mach >das mal mit 2^30 und beweise mir, dass dir die Konsole 0,5 anzeigt, was >sie nicht tun wird. 1.) kann man für Debugausgaben float/double benutzen, ist schnell genug. 2.) kann man das ganz einfach mit dem bekannten Schema aus der Schule berechnen und ausgeben. Der Haken liegt halt bei der Kodierung zur Basis 2, das macht die Sache ein wenig nerviger. "das entspricht 2^30 = 1073741824 als int gelesen .... das ist sehr wenig anschaulich." Klar. 2^30 / 2^31 = 1073741824 / 2147483648 = 0 Rest 1073741824 Hier setzt die normale Division ein, wie man sie mal gelernt hat. 1073741824 * 10 / 2147483648 = 5 Rest 0 Rest * 10 / 2147483648 ... -> 0,5 Klar, 2^30 * 10 > 32 Bit. Dafür gibt es zwei Lösungsmöglichkeiten. 1.) 64 Bit int 2.) die letzte Stelle in den Skat drücken und vor den Rechungen /2 teilen und immer / 1073741824 rechnen. >Naja, ich merks nach den paar Posts schon, dass man sich eh wieder nur >was anhören muss, wie dumm man ist... Nö, aber Kritik muss man schon einstecken können. Den C-Code dazu solltest du selber hinkriegen. Ob der dann effizienter als die Verwendung von double ist, bleibt offen.
Karl Heinz Buchegger schrieb: > stellst 0.5 mittels 50000 dar Dazu ist es natürlich nötig, das Zahlensystem (wenigstens mental) zu wechseln und auf einen richtigen Integer zu wechseln, und den dann auch darzustellen. Und wenn es eine negative Zahl ist, dann merk dir das, invertiere die Zahl und mach so weiter, wo Karl Heinz angefangen hat. Das wars dann... Alternativ könntest du deine 32-Bit-Zahl auch nur als Signed Integer ansehen und z.B. durch 21475 teilen. Lass dich überraschen, was dabei rauskommt...
265121435 / 2147483648 = 0 Rest 265121435 2651214350 / 2147483648 = 1 Rest 503730702 5037307020 / 2147483648 = 2 Rest 742339724 7423397240 / 2147483648 = 3 Rest 980946296 9809462960 / 2147483648 = 4 Rest 1219528368 12195283680 / 2147483648 = 5 Rest 1457865440 14578654400 / 2147483648 = 6 Rest ??? Overflow im Windows Taschenrechner
Naja, man könnte auch die krampfhafte Normierung von 1 = 2^31 = fallen 1.073.741.824 lassen und gescheit auf 1 = 1.000.000.000 normieren. Dann rechnet es sich 1. viel einfacher und schneller und man hat keine Problem mit nicht exakt darstellbaren Zahlen im 2er und 10er System . . . Wäre aber zu pragmatisch
Oder man muss halt für die Ausgabe mit einem 64-Bit-Zwischenergebnis rechnen:
1 | int32_t ausgabe = (int64_t) zahl * 1000000000 / (1L << 31); |
Warum nicht also Float. Ganz früher hatte ich mal einen Z80-Rechner (2MHz). Der hat in Basic immer mit floats gerechnet. Und selbst damit konnte man etwas vernünftiges anfangen. Letztens hatte ich einen TI2810 Mikrocontroller. Der hat Floats auch emuliert, und lief nur mit 100 MHz. Doch auch damit habe ich ADC-Werte sklaliert in normaler IEEE-754 Darstellung. Und der hatte noch Zeit für 1000 andere Dinge. So eine Float-Emulation kann genz schon schnell sein. Und bevor ich als Programmierer mit Festkommarechnung überfordert bin, probiere ich erst mal die Floats aus. Optimieren kann man später.
Franky schrieb: > Festkommazahlen Q0.31 Du kennst http://en.wikipedia.org/wiki/Q_%28number_format%29 http://en.wikipedia.org/wiki/Fixed-point_arithmetic http://en.wikipedia.org/wiki/Libfixmath mit http://code.google.com/p/libfixmath/ http://www.superkits.net/whitepapers/Fixed%20Point%20Representation%20&%20Fractional%20Math.pdf bereits? Grüße Stefan
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.