Geschickt runden

#2673065
Lesenswert?

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

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

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

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);
#2673205
Lesenswert?

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

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

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

> 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.
(Firma: guloshop.de) #2673290
Lesenswert?

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
#2673292
Lesenswert?

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

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

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

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

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.

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