PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Funktion Float2String



aircode
09.12.2009, 23:15
Hallo,

ich hab im Forum eine für mich sehr brauchbare Funktion gefunden und auch erfolgreich in Verwendung! Nur hab ich leider keine Ahnung warum das so funktioniert wie es funktioniert :-k

Könnte jmd die Funktion evtl. mit Kommentaren versehen - "Deppensicher" - also so dass ich es auch verstehe :-)

THX


void float2string(float value, int decimal, char* valuestring)
{
int neg = 0;
char tempstr[20];
int i = 0;
int j = 0;
int c;
long int val1, val2;
char* tempstring;
tempstring = valuestring;
if (value < 0) {neg = 1; value = -value;}
for (j=0; j < decimal; j++) {value = value * 10;}
val1 = (value * 2);
val2 = (val1 / 2) + (val1 % 2);
while (val2 !=0) {
if ((decimal > 0) && (i == decimal)) {
tempstr[i] = (char)(0x2E); //0x2E = Punkt
i++;
}
else {
c = (val2 % 10);
tempstr[i] = (char) (c + 0x30); //0x30 = Null
val2 = val2 / 10;
i++;
}
}
if (neg) {
*tempstring = '-';
tempstring++;
}
i--;
for (;i > -1;i--) {
*tempstring = tempstr[i];
tempstring++;
}
*tempstring = '\0';
}

Ceos
10.12.2009, 08:43
wenn der flash-speicher nicht an die grenzen geht, würde ich dir sprintf mit empfehlen, dazu musst du dann aber noch 2 libs und 3 compilerschalter einfügen, aber das geht ganz unkompliziert ^^

aircode
10.12.2009, 12:49
wenn der flash-speicher nicht an die grenzen geht, würde ich dir sprintf mit empfehlen, dazu musst du dann aber noch 2 libs und 3 compilerschalter einfügen, aber das geht ganz unkompliziert ^^

natürlich... und das ganze hab ich dann mit meinen Kenntnissen in 2 Min programmiert und dann löte ich noch schnell eine Futur-Microwelle auf meinen RP6 der mir dann auf Knopfdruck jede erdenkliche Speise zubereitet.
Immo hätte ich auf ein Budapester Gordonblue mit Kroketten lust ](*,)

Spaß bei Seite... ich bräuchte wirklich etwas Unterstützung

THX

Ceos
10.12.2009, 14:30
entschuldige, ich biete dir nur eine lösung an! wenn du gesagt hättest "ich hab genug flash über" hätt ich dir auch ganz genau vll. sogar mit bildern erklärt wie das geht .... ich wollt nicht nur gleich über dich herfallen mit input!


echt mal das geht auch freundlicher ... muss man nicht immer gleich a********* sagen

und by the way, mit sprinft geht das ganze mit deinen fähigkeiten und ein wenig hilfe in weniger als 2min zu schreiben und sogar in nur einer zeile!


Spaß bei Seite
du hast eine seltsame vorstellung von "Spaß"

aircode
10.12.2009, 20:17
Sorry, dass du meine microwelle so ernst genommen hast... war nicht böse gemeint... ganz im Gegenteil! Ich hab halt etwas schmunzeln müssen, als ich las, dass ich 2 neue libarys und 3 compilerschalter einfügen muss. Ich bin froh, wenn ich mal die Original-Lib so halbwegs verstehe... ganz zu schweigen von einer neuen/eigenen Lib... Naja, aber das wird schon... Hab leider immer erst Abends und meistens nur "kurz" Zeit mich mit dem Thema zu beschäftigen.

so, werde mal nach sprintf googlen...

Mfg

Aircode

Ceos
10.12.2009, 21:07
die libs kann man im avrstudio in den projekteinstellungen hinzufügen, einfach bei librarys nachsehen, eine heisst libprintf_flt.a und die andere libm.a, einfach hinzufügen

http://winavr.scienceprog.com/images/stories/2007/sprintf/AVR_Studio_Float.PNG

und dann bei custom options auf den linker gehen und folgende zeile über add einfügen

"-Wl, -u, vfprintf"

http://winavr.scienceprog.com/images/stories/2007/sprintf/AVR_Studio_Linker_Options.PNG


bilder stammen von
http://winavr.scienceprog.com/avr-gcc-tutorial/using-sprintf--function-for-float-numbers-in-avr-gcc.html

da stehts auch nochmal erklärt

aber wie gesagt die printf frisst relativ viel flashspeicher

EDIT: auch wie man es im makefile ändern muss steht drin, bzw. im programmers notepad

uwegw
10.12.2009, 21:32
Die wichtigste Zeile ist diese:
for (j=0; j < decimal; j++) {value = value * 10;}
Da passiert folgendes:
Alle Stellen, die uns interessieren, werden vor das Komma gebracht. Dazu wird die Zahl oft genug mit 10 multipliziert.
Beispiel: aus 3.1425 wird, bei Ausgabe von 2 Nachkommastellen, dann 314.25
Der Nachkomma-Anteil wird dann nicht mehr berücksichtigt, und der Rest wie bei der Umwandlung von int in string gemacht. Also die Stellen einzeln betrachten und das passende Zeichen (Ascii-Wert von Null addieren) in den String schreiben. Dabei wird dann noch das Komma an der richtigen Stelle eingefügt.

Diese Umwandlung würde ich aber anders machen. Denn in deinem Code wird dann ständig mit value gerechnet, und das braucht viel Zeit. Ich würde lieber nach der Verschiebung des Kommas den interessanten Teil der Zahl in einen long int kopieren. Damit rechnet es sich deutlich schneller.

Je mehr ich die Funktion betrachte, desto mehr Optimierungspotential fällt mir auf. So könnte man die entscheidende Zeile
for (j=0; j < decimal; j++) {value = value * 10;}
durch
if(decimal>0) value = value * (10 * decimal);
ersetzen. Dann hat man in der gesamten Funkton nur noch eine einzige float-Multiplikation, und wäre deutlich schneller.

aircode
10.12.2009, 21:41
Danke mal für die ersten Hilfeschritte...

Kannst du mir noch sagen was speziell diese Zeile macht:


tempstr[i] = (char)(0x2E); //0x2E = Punkt

THX

Aircode

uwegw
10.12.2009, 23:26
Das ist ne sehr blöde Schreibweise für
tempstr[i] = '.';
Es wird also an der Stelle i ein Punkt eingefügt.