Moin,
wenn ich eine Zahl wie 400.99999999999999 als double habe, wie kann ich
diese geschickt auf 401 runden? Alle anderen normalen Kommazahlen sollen
nicht gerundet werden.
Also diese Grenzwerte wegrunden?
mfg
int(400.99999999999999 + 0.x5 )
x sind so viel "0" wie du Stellen + 1 behalten willst
Denk mal über Integerberechnung nach.
Ist auf µC meistens die bessere Wahl.
Tommy T. schrieb:> y = 400.99999999999999;> y = (int)(y + 0.00000000000001)>> Rundet alle Zahlen auf 401 die >= 400.99999999999999 sind.>
Eigentlich ist es sogar besser, wenn du es nur so machst:
y = y + 0.00000000000001;
Dann musst du vor dem Runden nicht den Wert prüfen. Der Fehler für alle
wird dadurch (hoffentlich) minimal und ob man jetzt 400.99999999999999
oder 401.0 hat ist ja nur für die Ausgabe relevant.
Ralph schrieb:> Denk mal über Integerberechnung nach.> Ist auf µC meistens die bessere Wahl.
Was bringen mir Integer, wenn ich Frequenzen aus einem Integer berechne
(Timer werte) und den Wert aufm Display darstellen will?
Ich hatte versucht, den Double Wert zu runden und dann jeweils zu
addieren und subtrahieren. Wenn der Abstand dann kleiner als 0.001 ist,
soll gerundet werden. Das hat aber nicht funktioniert, da bei dem Wert
immer ne glatte 0 heraus kommt.
Curby schrieb:> wenn ich eine Zahl wie 400.99999999999999 als double habe, wie kann ich> diese geschickt auf 401 runden?
400.99999999999999 ist nur ein Artefakt der Dezimaldarstellung bei
deiner Ausgabe. Beschränke deine Ausgabe auf die Zahl der relevanten
Stellen und alles wird gut.
Werner schrieb:> Curby schrieb:>> wenn ich eine Zahl wie 400.99999999999999 als double habe, wie kann ich>> diese geschickt auf 401 runden?>> 400.99999999999999 ist nur ein Artefakt der Dezimaldarstellung bei> deiner Ausgabe. Beschränke deine Ausgabe auf die Zahl der relevanten> Stellen und alles wird gut.
Im sprintf wird daraus 400.999 bei %3.3f. Daraus sollte dann 401 werden.
Das problem des Rundens betrifft in diesem Fall natürlich nur die Grenze
zur nächstgrößeren Zahl. Aus 400.0000000001 wird der denke ich mal
400.000 machen.
Ich habe jetzt folgende umständliche Lösung verwendet, die auch
funktioniert. Die Variable freq_soll ist die betreffene Variable.
if((float)round(freq_soll)-freq_soll < 0.001 &&
(float)round(freq_soll)-freq_soll > 0) freq_soll = round(freq_soll);
> Was bringen mir Integer, wenn ich Frequenzen aus einem Integer berechne> (Timer werte) und den Wert aufm Display darstellen will?
Sie bringen das mathematisch einzig richtige Ergebnis. Du kannst durch
Berechnungen keine höhere Genauigkeit erzeugen, als Deine Ausgangswerte
besitzen. Und wenn die ungenaueste Zahl NULL Nachkommastellen hat, dann
darf das Ergebnis auch nur NULL Nachkommastellen besitzen. Alles andere
ist ein Lügenbold, Schätzeisen, oder wie auch immer Du das nennst.
Eben, denn wer will im allgemeinen Fall entscheiden, ob die Zahl
zufällig oder zurecht diesen Wert angenommen hat. Das Einige, was es zu
beachten gibt, ist, sie so zu runden, dass kein wesentlich grösserer
Fehler entsteht, als die Zahl ohnehin in sich trägt und aus Sicht des
Ingenieurs ist es sogar nötig, sie so zu runden, dass nicht der Eindruck
einer künstlichen Genauigkeit entsteht, als nicht zuviele Stellen
anzuzeigen.
Was mir noch nicht klar ist:
Warum funktioniert die Addition von 0,5 nicht?
Die 401.49999 müssten doch auch korrekt abgerundet werden. Angenommen,
die 3. Stelle soll erhalten werden, dann müssten mathematisch 0,0005
addiert werden. 401,000499000 und damit genau 401,000.
Excel kann das auch:
400,9999
+ 0,0005
401,0004
wobei Excel bereits auf 401 rundet, wenn man die 400,9999999 mit
zuvielen Stellen eingibt :-)
Ein anderes Problem ist, dass man bei der Gaussklammerfunktion oder
Gaussrundung nicht mit 1,0 arbeiten darf sondern mit 0,999999999 rechnen
muss.
Martin Schwaikert schrieb:>> Was bringen mir Integer, wenn ich Frequenzen aus einem Integer berechne>> (Timer werte) und den Wert aufm Display darstellen will?>> Sie bringen das mathematisch einzig richtige Ergebnis. Du kannst durch> Berechnungen keine höhere Genauigkeit erzeugen, als Deine Ausgangswerte> besitzen. Und wenn die ungenaueste Zahl NULL Nachkommastellen hat, dann> darf das Ergebnis auch nur NULL Nachkommastellen besitzen. Alles andere> ist ein Lügenbold, Schätzeisen, oder wie auch immer Du das nennst.
Da will ich jetzt doch mal nachhaken. Z.b. ich habe den Timerwert 10000
und 1 entspricht 1/F_CPU Sekunden, dann ist meine Frequenz ja
F_CPU/Timerwert. Der ursprüngliche Wert ist eine INT das ist klar, aber
das Ergebnis kann ja allmöögliche Kommastellen annehmen, da brauch ich
doch eine Kommazahl, eben float oder double.
> 401,00049900
Höchts wahrscheinlich deshalb, weil deine 401,00049900 in Wirklichkeite
eben 401.0004989999999 sind, welche dann bei der Ausgabe auf 401.000499
aufgerundet wurden.
> Excel kann das auch
Excel rechnet aber auch nicht mit float. Es macht nun mal einen
Unterschied, ob du 6 signifikante Stellen hast oder 15.
Curby schrieb:> wenn ich eine Zahl wie 400.99999999999999 als double habe, wie kann ich> diese geschickt auf 401 runden? Alle anderen normalen Kommazahlen sollen> nicht gerundet werden.
Schaut ja schlimm aus. :-)
Nimm doch Festkommazahlen, dann hast du solche Probleme gar nicht erst.
Zusätzlich werden die Berechnungen deutlich schneller.
http://www.mikrocontroller.net/articles/Festkommaarithmetik
Curby schrieb:> Da will ich jetzt doch mal nachhaken. Z.b. ich habe den Timerwert 10000> und 1 entspricht 1/F_CPU Sekunden, dann ist meine Frequenz ja> F_CPU/Timerwert. Der ursprüngliche Wert ist eine INT das ist klar, aber> das Ergebnis kann ja allmöögliche Kommastellen annehmen, da brauch ich> doch eine Kommazahl, eben float oder double.
Das Problem ist ein anderes.
Du musst dich fragen, wieviele Kommastellen sind denn überhaupt
relevant? Und darauf musst du deine Berechnung anpassen.
Und: Du musst beim Rechnen mit Floating Point immer berücksichtigen,
dass du im Rechner nur eine endliche Genauigkeit hast. Die naive
Annahme, das Floating Point Rechnerei genau gleich funktioniert wie in
der Mathematik, ist ein Irrglaube.
> Der ursprüngliche Wert ist eine INT das ist klar, aber das Ergebnis> kann ja allmöögliche Kommastellen annehmen, da brauch ich> doch eine Kommazahl, eben float oder double.
nein:
Du erweiterst den Quotenten um 10 oder 100 und schmuggelst bei der
Ausgabe ein Komma rein:
z.B. Runden und Ausgeben mit 2 Nachkommastellen
F_CPU = 16000000
Timer = 3
Berechnung:
FoutMal100 = F_CPU * 100 / timer ;
FoutVorkomma = FoutMal100 / 100 ;
FoutNachkomma = FoutMal100 % 100 ;
eProfi schrieb:>> Der ursprüngliche Wert ist eine INT das ist klar, aber das Ergebnis>> kann ja allmöögliche Kommastellen annehmen, da brauch ich>> doch eine Kommazahl, eben float oder double.>> nein:> Du erweiterst den Quotenten um 10 oder 100 und schmuggelst bei der> Ausgabe ein Komma rein:> z.B. Runden und Ausgeben mit 2 Nachkommastellen> F_CPU = 16000000> Timer = 3>> Berechnung:> FoutMal100 = F_CPU * 100 / timer ;> FoutVorkomma = FoutMal100 / 100 ;> FoutNachkomma = FoutMal100 % 100 ;
Ich hab aber Werte im Timer von 0-262143 (jap, es handelt sich hier
sogar um eine Long)? Das Fließkommaberechnung nicht exakt genau ist, ist
mir durchaus bewusst. Aber so genau, wie ich es brauche wird es wohl
sein.
Martin Schwaikert schrieb:> Und wenn die ungenaueste Zahl NULL Nachkommastellen hat, dann> darf das Ergebnis auch nur NULL Nachkommastellen besitzen. Alles andere> ist ein Lügenbold, Schätzeisen, oder wie auch immer Du das nennst.
Was hat das mit der Zahl der Nachkommastellen zu tun. Die kann man
beliebig ändern, indem man ein Spannung z.B. statt in mV in V angibt.
Entscheidend ist die Anzahl der gültigen Stellen. Ein Widerstand von
2,26MΩ wird nicht dadurch genauer oder ungenauer, dass man ihn als
2260000Ω angibt.
Werner schrieb:> Martin Schwaikert schrieb:>> Und wenn die ungenaueste Zahl NULL Nachkommastellen hat, dann>> darf das Ergebnis auch nur NULL Nachkommastellen besitzen. Alles andere>> ist ein Lügenbold, Schätzeisen, oder wie auch immer Du das nennst.>> Was hat das mit der Zahl der Nachkommastellen zu tun. Die kann man> beliebig ändern, indem man ein Spannung z.B. statt in mV in V angibt.> Entscheidend ist die Anzahl der gültigen Stellen. Ein Widerstand von> 2,26MΩ wird nicht dadurch genauer oder ungenauer, dass man ihn als> 2260000Ω angibt.
Oh ja richtig. gültige- nicht Nachkommastellen. verzeihung.