Int to float riesiger Speicherbereich

Gast #3045227
Lesenswert?

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?
1
float a; 
2
float b;
3
float c;
4

5
uint8_t e;
6

7
c= a/b;
8

9
c=c+0,5;
10

11
e = (uint8_t)c;

Danke schonmal im Voraus
Gast #3045273
Lesenswert?

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?
Gast #3045283
Lesenswert?

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
Gast #3045302
Lesenswert?

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...
Gast #3045386
Lesenswert?

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.
Gast #3045429
Lesenswert?

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.
Gast #3045473
Lesenswert?

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.
Persönliche Seite #3045715
Lesenswert?

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.
Persönliche Seite #3045734
Lesenswert?

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.
#3045790
Lesenswert?

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.
#3045822
Lesenswert?

...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
Gast #3046100
Lesenswert?

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!
Gast #3047055
Lesenswert?

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.
Gast #3047082
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren