Hallo zusammen,
Ich habe folgendes "konstrukt" Programmiert leider benötigen die
Codezeilen knapp 40% meines kompletten Code-speichers von meinem Atmega
8....
Ziel ist es die nachkommastellen "abzuschneiden"
Kann man dies auch Speicherplatz schonender programmieren?
simso schrieb:> Ich habe folgendes "konstrukt" Programmiert leider benötigen die> Codezeilen knapp 40% meines kompletten Code-speichers von meinem Atmega> 8....
Den Speicher benötigt nicht diese eine Code-Zeile, sondern die Tatsache,
dass du Float-Zahlen verwendest und der Linker die dafür benötigten
Bibliothek mit einbindet.
Wozu brauchst du auf einem µC Float?
Fabian O. schrieb:> Man kann es auf jeden Fall wesentlich kürzer hinschreiben:
Und du meinst, das sich dadurch der Umfang des erzeugten Codes
nennenswert ändert?
Vielen Dank erstmal für die Infos,
Den Artikel mit der Festkommaarithmetik hatte ich bereits gelesen...
Ich habe mich auch nochmal schlau gemacht und dabei die Funktion
dtostrf() gefunden. Werde Morgen mal meinen Code auf double Umbauen und
dann nochmals Versuchen. Habe heute keine Lust mehr ;-)
Viele Grüße
simso schrieb:> Den Artikel mit der Festkommaarithmetik hatte ich bereits gelesen...
Ok, und weiter? Du sollst ihn nicht des Lesens wegen lesen, sondern weil
er dein Problem lösen kann. Wenn du ihn schon ignorierst, dann schreib
wenigstens warum. Aber deiner Frage nach bist du nicht kompetent genug,
um solche Vorschläge einfach im Vorbeigehen wegzuwischen.
> Ich habe mich auch nochmal schlau gemacht und dabei die Funktion> dtostrf() gefunden. Werde Morgen mal meinen Code auf double Umbauen und> dann nochmals Versuchen. Habe heute keine Lust mehr ;-)
Super! Du möchtest den Speicherverbrauch reduzieren, also nimmst du
einfach den nächstgrößeren Datentyp. Das funktioniert sicher...
simso schrieb:> Werde Morgen mal meinen Code auf double Umbauen und> dann nochmals Versuchen.
Den Unterschied zwischen Double- und Float-Variablen kennst du?
C-Programmierer schrieb:> simso schrieb:>> Werde Morgen mal meinen Code auf double Umbauen und>> dann nochmals Versuchen.>> Den Unterschied zwischen Double- und Float-Variablen kennst du?
Nun mal bitte langsam. Das kommt erst übermorgen dran.
C-Programmierer schrieb:> Und du meinst, das sich dadurch der Umfang des erzeugten Codes> nennenswert ändert?
Der ist identisch (wenn man mit Optimierung compiliert). Wozu also fünf
Zeilen schreiben, wenn es in einer viel übersichtlicher ist?
simso schrieb:> c=c+0,5;
Diese Zeile ist ein Bug. Sie ist äquivalent zu c+0;c =5;.
Auf einem 8 Bit uC werden 32 Bit IEEE754 Floats immer riesigen lahmen
Code brauchen. Sollest du wirklich 32 Bit Floats brauchen dann nimm nen
32 Bit uC mit Hardware FPU. Ansonsten schreibe deinen Code um.
simso schrieb:> leider benötigen die> Codezeilen knapp 40% meines kompletten Code-speichers von meinem Atmega
Ja sagt mal ihr alle zusammen, wie winzig ist denn der Codespeicher
dieses Atmegas oder andersherum: wie elefantös ist denn die
Gleitkommalib bei diesen uC? Ist vielleicht immer automatisch die ganze
sprintf(...) Lib mit dabei?
Ansonsten sind Bemerkungen wie
foo schrieb:> Sollest du wirklich 32 Bit Floats brauchen dann nimm nen> 32 Bit uC mit Hardware FPU. Ansonsten schreibe deinen Code um.
nicht wirklich hilfreich. Auch auf einem 8 Bitter braucht man
Gleitkomma, wenn man es mit Meßwerten und deren Kalibrierung zu tun hat.
Simples Beispiel: Reziprokzähler, wo der Quotient aus 2 größeren
Zählständen (long) gebildet werden muß und man auch Nachkommastellen auf
dem Display sehen will.
W.S.
W.S. schrieb:> Simples Beispiel: Reziprokzähler, wo der Quotient aus 2 größeren> Zählständen (long) gebildet werden muß und man auch Nachkommastellen auf> dem Display sehen will.
Was hat Float jetzt mit Nachkommastellen zu tun?
Float hat verglichen mit einer gleich großen Fixkommazahl eine
verringerte Genauigkeit, weil etliche Bits für den Exponenten verbraucht
werden. Dafür ist der Dynamikbereich größer, was aber für viele
Anwendungen, die sich in einem festen Zahlenbereich abspielen, überhaupt
keine Rolle spielt.
simso schrieb:> Ich habe folgendes "konstrukt" Programmiert leider benötigen die> Codezeilen knapp 40% meines kompletten Code-speichers von meinem Atmega> 8....
Das "Konstrukt" enthält float +, / und Konvertierung nach int.
Meine Erfahrung mit float ist, daß es weniger Platz verbraucht als die
von dir genannten ca. 3kB.
Projekt 4000 Stellen von Pi mit ATtiny2313 passt zum Beispiel in
einen ATtiny2313 und verwendet folgende float-Routinen:
+, -, *, /, lrintf, floorf, Konvertierung von int nach float.
Zudem enthalten die 2kB Code ausser float-Arithmetik noch andere Sachen
wie UART-Ausgabe und Integer-Arithmetik modulo n, nämlich Multiplikation
mod n und Exponentiation mod n.
Zumindest früher wars doch so, dass avr-gcc die falschen recht
monströsen Libfunktionen für Fliesskommarechnung verwendete, wenn man
vergass, dem Linker den richtigen Tipp zu geben. Meist merkten es die
Leute, weil das RAM platzte.
In der aktuellen Version des Compiler ist das nicht mehr so —
vorausgesetzt, der Compiler wurde adäquat konfiguriert:
http://gcc.gnu.org/PR54461
D.h. auch ohne -lm werden immer die optimierten Routinen der AVR-LibC
verwendet; in der libgcc.a sind sie nämlich nicht mehr vorhanden.
Ausserdem wird -lm automatisch durch den Compiler gesetzt. Grund ist,
daß die libm.a float-Routinen enthält, die über math.h hinaus gehen,
nämlich Operationen wie + und * welche zum Sprachkern gehören.
Daher muss man sich um das Setzen von -lm ebenso wenig kümmern wie um
das Setzen von -lc oder -lgcc.
Johann L. schrieb:> In der aktuellen Version des Compiler ist das nicht mehr so
Viele haben nicht die Zeit und Lust, ständig der neuesten Version
nachzujagen.
Es ist auch eine Frage der Zuverlässigkeit. Wenn viel Code und
Bibliotheken mit einer bestimmten Compilerversion erstellt und getestet
wurden, dann bleibt man möglichst lange dabei.
Z.B. der Keil C51, den wir benutzen, ist von 1995.
Der WINAVR-2010 braucht -lm.
Und da der Code ja um 3kB angestiegen ist, braucht er es auch.
...falls es noch keiner geschrieben hat:
Ein pragmatischer Ansatz ist:
Überlege wie genau das Ergebnis sein muss bzw. welchen Werteberiech a
und b haben.
Angenommen, Dein Wertebereich wäre nicht größer als 0..655 und Du
möchtest zwei Nachommastellen, dann nimmst Du für die Variablen (bis auf
e) uint16_t und alle Werte *100 und am Ende machst Du dann ein
e = (c+50)/100;
Wenn man damit leben kann, eine Genauigkeit von z.B. 1/256 zu haben, und
der Wertebereich 0..255 ist, kann man auch einfach alle Werte *256
nehmen und im letzten Schritt /256, das ist für den Compiler SEHR
einfach zu übersetzen.
Grüße
Markus
An alle die hier konstruktiv beigetragen haben:
das mit dem Double war gestern Abend natürlich ne "Schnapsidee" ;-)
So wie W.S. geschrieben hat muss ich leider diese Division durchführen
.
Habe die ganze Zeit AVR Studio 4 Benutzt nun habe ich mir das neue Atmel
Studio 6 installiert und siehe da anstatt 40% Speicher braucht die
Division nur noch 10% Speicher und dass kann ich in meinem
Anwendungsfall verkraften;-).
PS: Zu den ersten Beiträgen: Wenn ich schon 20Jahre Erfahrung in C
Programmierung hätte und so wie einige geschrieben haben ne hohe
Kompetenz hätte müsste ich hier keine Postings zu diesem Thema
durchführen.
Das nächste mal einfach nicht antworten oder etwas die Etikette wahren.
Danke!
OK, das Problem ist erledigt.
Trotzdem noch ein Nachtrag von mir:
Michael schrieb:> Was hat Float jetzt mit Nachkommastellen zu tun?
Wo in der Programmiersprache C gibt es überhaupt Nachkommastellen? Etwa
bei char, int, long ? nee. nur in float bzw. double
Oder andersherum:
Teile mal 9899373 durch 10000012 und komme dabei drauf, daß der
verwendete Referenzoszillator eben 10.000012 MHz hat und die zu
vermessende Signalquelle 9.899274 MHz. In Assembler ist das gar kein
Problem, da macht man sowieso alles zu Fuß, aber formuliere sowas mal
gescheit in C - du Naseweis.
W.S.
W.S. schrieb:> aber formuliere sowas mal gescheit in C - du Naseweis.
Wenn man das gescheit rechnen möchte, gibtst du deine Frequenzen z.B. in
Hz an. Quotienten nahe 1 kannst du immer mit einer Reihenentwicklung
deiner Division, die du nach dem liniearen Glied abbrichst, erschlagen.
Mit Float bekommst du deine Zahlen schon von der Genauigkeit her nicht
mehr dargestellt.