float in string?
-
hmm jo danke erstmal, mit dem 1234568 funktionisert es, nur ergibt sich hier dann dieses Problem bei folgender Operation:
float a = 1234567; a = a + 1.11; printf("Result: %.20g\n\n", a);
Ergebnis: 1234568.125
sollte da nicht: 1234568.11 rauskommen? Und wenn ich mehr bei .20 angebe, z.B. .30 kommt dasselbe raus.
Gruss,
~cp
-
Vielleicht solltest du dich mal mit der internen Funktionsweise von float auseinandersetzen.
Um das ganze abzukürzen: Deine Zahl ist zu groß für float oder besser gesagt, sie ist zu groß um eine gewisse Genauigkeit zu garantieren. Verwende doch anstatt float double, dann sollte das Problem weg sein, allerdings nur solange du auch da nicht zu große Zahlen speicherst.
-
@AJ: Hi, ja ich habs auch schon mit double probiert, aber da kommt dann auch nur Müll hinten raus ...
-
sorry für den falschen post
hast mich jetzt so stark interessiert das ich es auch probieren wollte.
dabei ist folgender code rausgekommen. ist höchstwahrscheinlich nicht der schönste oder sinnvollste aber es geht. beim cutten bin ich mir nicht ganz sicher da ich einfach das string immer terminiere, aber es wird bestimmt jemand dazu was sagen#include <stdio.h> #include <stdlib.h> #include <string.h> void DoubleToString(double d, char *pString) { if(!pString) return; int nSize = sprintf(pString, "%f", d); int nPos = strcspn(pString, "."); for(int i = nPos + 1; i < nSize; ++i) if(pString[i] != 48) return; strtok(pString, "."); } void Cut(char *pString) { for(int i = strlen(pString); i > 0; --i) if(pString[i] == 48) pString[i] = '\0'; } int main(int argc, char *argv[]) { char szTemp[80]; double d = 1234567.89; DoubleToString(d, szTemp); Cut(szTemp); printf("Double To String: %s\n", szTemp); system("pause"); return 0; }
-
Ich habe mich auch mal daran versucht. Bin da allerdings etwas anders rangegangen, z.B. gibt meine Funktion auch nur aus, aber das ist ja kein Problem zu ändern.
void print(double d){ char b1[21]; char b2[23]; sprintf(b1,"%.20g",floor(d)); sprintf(b2,"%g\n",fabs(fmod(d,1.0))); printf("%s%s",b1,&b2[1]); } int main(){ float a = 1234567; a = a + 1.11; print(a); return 0; }
Gruß
Entyl Sa
-
Huhu
Ja erstmal danke für eure Hilfe! Ich hatte da auch sowas ähnliches gemacht wie miller_m, nur mit'ner for-Schleife:
double a = 999549; a += 1.134; char test[1024]; sprintf(test, "%lf", a); for(int i=strlen(test)-1;i>0;i--) { if(test[i] != '0' || test[i] == '.') { test[i+1] = '\0'; break; } } printf("Result: %s\n", test);
Mir gefällt das von Entyl_Sa aber am besten, ich denke das nehme ich! Vielen Dank, Leute
~code_pilot :p
-
@Entyl_Sa
bei deinem bsp. kommt aber bei mir 1234568.125 raus
-
Das ist in der Tag etwas Merkwürdig. Liegt aber nicht an meiner seziellen Funktion, sondern scheint standardmäßig aufzutreten. Bsp.:
float a = 1234567; a = a + 1.11; printf("%.20e\n",a); //liefert 1.23456811000000010000e+006 fflush(stdout); printf("%.20e\n",a); //liefert 1.23456812500000000000e+006
Genau so verhält sich meine Funktion auch, wenn ich sie vor printf aufrufe liefert sie das richtige, wenn nacher entsprechend das andere.
Dafür hätte ich im übrigen auch gerne eine Erklärung, also bitte jemand liefern
[edit]OK, ich habe eine Erklärung gefunden[\edit]
-
Entyl_Sa schrieb:
float a = 1234567; a = a + 1.11; printf("%.20e\n",a); //liefert 1.23456811000000010000e+006 fflush(stdout); printf("%.20e\n",a); //liefert 1.23456812500000000000e+006
es wird immer besser
dein code liefert bei mir immer (also beide werte) 1.23456812500000000000e+006nt4.0 + servicepack 6
[schleichwerbung] meine funktionon gehen da ich nur das string ändere [/schleichwerbung]
-
Deine Funktion liefert bei mir, wenn ich den Double so aufbaue wie bei mir auch, genau das gleiche (1234568.125). Also sieh selbst:
int main(int argc, char *argv[]) { char szTemp[80]; float d = 1234567; d = d + 1.11; DoubleToString(d, szTemp); Cut(szTemp); printf("Double To String: %s\n", szTemp); system("pause"); return 0; }
Ich brauche keine Werbung, mein Code spricht für sich selbst. *kotz*
-
und warum willst du double aufbauen ?
wenn ich es aufbau wie du kommt bei mir 1234568.11 raus ?!?
könnte vielleicht an irgendwelchen rundungsfehler der fpu liegen oder an der plattform ?
[edit] wert
-
AJ schrieb:
Vielleicht solltest du dich mal mit der internen Funktionsweise von float auseinandersetzen.
Um das ganze abzukürzen: Deine Zahl ist zu groß für float oder besser gesagt, sie ist zu groß um eine gewisse Genauigkeit zu garantieren.
Ich wiederhole mich ungern im selben Thread, aber anscheinend ist es nötig!
-
Entyl_Sa schrieb:
Ich brauche keine Werbung, mein Code spricht für sich selbst. *kotz*
Ähm ... könnte mir jetzt bitte mal jemand sagen was am besten funzt
? Weil Entyl_Sa's Beispiel (habe ich aus der Funktion rausgenommen) geht ohne Probleme:
double a = 1234567; a += 1.11; char b1[20]; char b2[20]; sprintf(b1,"%.20g",floor(a)); sprintf(b2,"%g\n",fmod(a,1.0)); printf("Method-2 Result: %s%s\n",b1,&b2[1]);
Das liefert, wie es sein sollte
Method-2 Result: 1234568.11
Habe das auch unter Windows NT (Service Pack 6) getestet. Hmm ich teste das mal nachher auf meinem Notebook mit Win 98...
Gruss,
~cp code_pilot
-
@AJ: Das ganze ist schon klar, zumindistens mir. Ändert aber nichts an der Tatsache, das die Zahl nicht schön ausgegeben wird. Unsere Funktionen machen genau das.
float a = 1234567; a = a + 1.11; printf("%.20e\n",a); //liefert 1.23456811000000010000e+006 fflush(stdout); printf("%.20e\n",a); //liefert 1.23456812500000000000e+006
Mein Problem das hier zwei unterschiedliche Ausgaben erzeugt werden habe ich dann auch auf das Genauigkeitsproblem zurueckgeführt. Ich dachte halt erst das er für ein und den selben Float die geliche Ausgabe erzeugen müßte. Bin aber dann zu dem Schluß gekommen das bei der ersten Ausgabe einfach noch der Double genutzt wird der noch im Register liegt, und bei der zweiten dann halt erst der schon zu
Float konvertierte Wert, mit mangelnder Genauigkeit.@miller_m: Wenn du Float anstelle von Double benutzt, dann kommt bei dir wahrscheinlich das gleiche raus wie bei mir auch. Das einzige Problem bei meinem Code ist das negative Zahlen nicht richtig ausgegeben werden, das werde ich aber jetzt gleich ändern.
-
code_pilot schrieb:
Ähm ... könnte mir jetzt bitte mal jemand sagen was am besten funzt
?
Wie ich in meinem letzten Post bereits erwähnt habe existiert noch ein Problem bei negativen Zahlen. Ausserdem ist mir gerade aufgefallen das es auch zu Problemen bei bestimten Nachkommazahlen gibt. Ich melde mich wenn mir eine Lösung eingafallen ist.
miller_m´s Funktion ist allerdings auch noch nicht ganz perfekt, z.B. bei 0.001 gibt er nur "0." aus.
-
Wenn sogar double nicht ausreicht, dann könntest du auch noch nach Bibliotheken suchen, die noch größere Fließkommazahlen zur Verfügung stellen. Konkretes weiß ich leider darüber aber nicht, nur dass es solche Bibliotheken gibt. Allerdings verwundert es mich sehr, dass es mit double nicht gehen sollte. Wie hat denn dein Formatstring ausgesehen als du es mit double versucht hast?
PS: @Entyl_Sa
Ja hab schon gesehen, dass du es schon bemerkt hast :). War nur deswegen, weil schon zum 2. mal nach meiner Erklärung nochmal danach gefragt wurde ;).PS: @code_pilot
Ich vermute mal du hast den double einfach mit %g ausgegeben, richtig? Für double musst du ein l noch einbauen, also %lg, sonst konvertiert er deinen double wieder in einen float und somit hätte sich nichts geändert ;).
-
Das Problem ist zu verhindern das die expotential Schreibweise verwendet wird, aber auch keine überflüssigen Nullen vorhanden sind.
Und das geht mir jetzt echt auf den Kecks das ich das nicht hinbekomme.
-
Huhu, ich habe jetzt endlich eine funktionierende Lösung (auch mit negativen Zahlen):
double calcNum = 1234567.8; calcNum += 1.1; sprintf(text, "%lf", calcNum); for(int a = strlen(text)-1;a>0;a--) { if(text[a] == '.') { text[a] = '\0'; break; } if(text[a] != '0') { text[a+1] = '\0'; break; } } printf("%s\n", text);
~code_pilot
-
Buggy Forum (s.o.) ???
-
Sowas ist mir auch schon in den Kopf gekommen, aber ich hätte das ganze halt gerne irgendwie über printf gelöst.