Rundungsfehler in eigener Funktion
-
Hallo,
schreibe im Moment an nem MatheProgramm für meine facharbeit der Jgst. 12.
Ich weiß, es ist kein ANSI C++, ich muss halt nen Array aus Punkten den ich von der Maus empfange mit Linien verbinden, undzwar halt genau so wie die GDI das macht(Bsp: Auch Paint empfängt halt nur einzelne Punkte, verbindet diese aber untereinander mit Linien!).So, ich mache das jetzt halt mit Steigungsdreieck, etc, die Ergebnisse sind auch zu 98% wirklich gut, bin auch froh dass ich das bis jetzt schon geschafft habe, aber für ne Mathe Facharbeit sollten es schon 100% Richtigheit sein
Also, mein Fehler liegt in der von mir selbst geschriebenen Rundungsfunktion für Floats, und das ist halt mein ANSI-C++ Problem
:
int round(float value) { float rest=value-int(value); if(rest==0.500000) return int(value+0.5f); else if(rest<0.500000) return int(value-rest); else return int(value+(1-rest)); }
Soll heißen, die Funktion soll als Rundungsgrenze 0.5 nehmen. Kennt ihr sicher, Beispiele dafür :
x.3 -> x
x.49 -> x
x.5 -> x+1
x.8 -> x+1Mein Problem ist aber : Auß einem mir nicht ersichtlichen Grund rundet die Funktion auch bei x.5 ab, d.h. auch 3.5 wird zu 3 gerundet. Lustigerweise tut sie das aber nicht immer, sondern nur wenn x>2. D.h. 0.5 wird korrekt zu 1 gerundet, 1.5 wird korrekt zu 2 gerundet, aber alles >2, also z.b. 2.5,3.5,4.5 etc werden ab(also falsch) gerundet!
Meine Frage nun : Warum ist das so, kann doch rein aus der logik her schonmal garnet sein weil ich ja auf "rest==0.5f" prüfe... Und warum verhält sich die Funktion für x<2 korrekt, für x>2 aber falsch??? Bin ich zu blöd oder ist das ein Compilerfehler????
Alternativ könnt ihr mir natürlich auch eine einfache und gut funktionierende(vor allen dingen korrekt funktionierende) ANSI-C++ Funktion zum Runden von floats nennen
THX
Philipp
-
ich denke, du brauchst
int round(float value) { return int(value+0.5); }
-
Liefer genau die gleichen Ergebnisse...
Hier ein bild dazu aus dem testprogramm/Kommandozeile:
http://www.codetown.de/stuff/error.jpg
Philipp
-
Mhhh mir ist nochwas aufgefallen:
Wenn ich die round-Funktion so teste, liefer er für den wert 3.5 die zahl 3 zurück, rundet also falsch!
for(float i=3.0f;i<=4.1;i+=0.01f) { cout<<"Zahl:\t"<<i<<"\tGerundete Zahl(round):\t"<<round(i)<<endl; }
Wenn ich aber so teste, liefer er für 3.5 4 zurück, rundet also richtig:
cout<<"Zahl:\t"<<3.5<<"\tGerundete Zahl(round):\t"<<round(3.5)<<endl;
Warum macht der das?
Philipp
-
Vielleicht wird es dir klarer, wenn du dir folgendes ausgeben lässt:
for(double i=3.0f;i<=4.1;i+=0.01f) { cout<<"Zahl:\t"<<fixed<<setprecision(10)<<i<<"\tGerundete Zahl(round):\t"<<round(i)<<endl; }
Als kleiner Ratschlag: Verwende nicht Gleitkommazahlen in for Schleifen.
Die sind nämlich niemals ganz genau, und mit der Iteration wird der Wert immer ungenauer. Folgendes sollte zB korrekte Ergebnisse liefern:for (int i = 300; i < 410; ++i) { cout << "Zahl: " << i/100. << "; Gerundet: " << round(i/100.) << '\n'; }
-
davie schrieb:
Folgendes sollte zB korrekte Ergebnisse liefern:
for (int i = 300; i < 410; ++i) { cout << "Zahl: " << i/100. << "; Gerundet: " << round(i/100.) << '\n'; }
leider nein.
beispiel mit meinen vierstelligen dezimalzahlen:
floor(1.000/3.0003.000)
==floor(0.33333.000)
==floor(.9999)
==0.0000
aber
floor(2.000/3.0003.000)
==floor(0.66673.000)
==floor(2.001)
==2.000
bei diesen vierstelligen dualzahlen wirds im nachkommabreich ungenau, sobald man durch 3,6,7,9,11,12,13 oder sonst irgend ne zahl, die nicht produkt aus 2-en und 5-en ist, teilt.sobald man auf dem rechner mit seinem dualsystem als divisor keine zweierpotenz benutzt, wirds im nachkommabereich ungenau, und 100 ist leider keine zweierpotenz.
-
int round(float value) { return (int)value+0.5; }
Es funktioniert, wenn der cast weggelassen wird, da sonst eine
Integeraddition durchgefuehrt wird und keine Addition von
float-Werten.mfg
v R
-
virtuell Realisticer schrieb:
int round(float value) { return (int)value+0.5; }
Es funktioniert, wenn der cast weggelassen wird, da sonst eine
Integeraddition durchgefuehrt wird und keine Addition von
float-Werten.mfg
v Rdeswegen schreibt man ja uch
return int(value+0.5);
oder
return (int)(value+0.5);//hoch lebe der alte castder cast ist nur da, die compilerwarnung wegzudrücken.
-
Ich glaube, ich muss mal meine Einstellungen bezueglich Warnungen etwas
haeter einstellen, denn der BuilderX hat mir keine Warnung ausgegeben
(was er ja eigentlich haette machen muessen, schliesslich geht ja die
Genauigkeit floeten)mfg
v R