cast auf int
-
Hallo,
ich habe hier einen simplen Cast, der mich gerade etwas verwirrt:
int max = static_cast<int>( (g_maxRadius - g_minRadius) / g_stepsizeRadius );g_maxRadiust = 4.0f, g_minRadius = 3.0f und g_stepsizeRadius = 0.1f. Eigentlich müsste er doch dann einfach 10.0f auf int casten. Macht er aber nicht: Nach der Anweisung steht 9 in max.
Teile ich die Anweisung in 2 Anweisungen auf, so geht es seltsamerweise:
float ff = (g_maxRadius - g_minRadius) / g_stepsizeRadius; // ff ist 10.0f int max = static_cast<int>( ff );// max ist 10
Wahrscheinlich übersehe ich gerade was total triviales, aber im Moment versteh ich das Verhalten nicht. Kann mir das einer erklären, wieso in der oberen Anweisung 9 statt 10 rauskommt?
-
Es liegt an der Genauigkeit. Es kommt oben bei dir (wahrscheinlich wegen den
ganzen Ungenauigkeiten) 9,999... raus. Das wird dann auf 9 gerundet (nicht auf
10 wie man in der Schule gelernt hat!!!)
-
Dann müsste doch auch in ff 9.999999999999 stehen?
-
Hm... *weitergrübl*
-
Bei der Konvertierung in einen Gleitkommatypen geringerer Genauigkeit ist ggf. zu runden. Der C++-Standard überlässt es der Implementation zu entscheiden, wie zu runden ist (Im Gegensatz zur Konvertierung in Integer, dort schreibt der C++-Standard vor, dass der gebrochene Anteil der Zahl einfach verworfen wird). Eine IEEE 754-konforme Implementation muss allerdings zur nächsten im kleineren Zahlenformat exakt darstellbaren Zahl runden.
Die direkte Konvertierung in ein int schneidet also Nachkommastellen ab, die vorherige Konvertierung in ein float führt dagegen möglicherweise zu einem aufrunden, sofern der relative Fehler des Operanden klein genug ist - folglich ist das kein wirklich geeignetes Mittel, um solche Probleme allgemein zu lösen.
-
Hm, find ich ziemlichen Mist sowas. Naja, gäbe es denn überhaupt ne elegantere Methode als es einfach aufzusplitten in 2 Anweisungen?
-
int main(int argc, char *argv[]) { float g_maxRadius = 4.0f; float g_minRadius = 3.0f; float g_stepsizeRadius = 0.1f; float x = (g_maxRadius - g_minRadius); std::cout << "sub= "<<x <<std::endl ; float y = x / g_stepsizeRadius; std::cout << "div= "<<y<<std::endl ; int max = static_cast<int>( y ); std::cout << "max= "<<max<<std::endl ; return EXIT_SUCCESS; }
sub= 1
div= 10
max= 10
Press Enter to continue!:xmas1:
EDIT: okay, also kein aufspalten
-
this->that schrieb:
Hm, find ich ziemlichen Mist sowas. Naja, gäbe es denn überhaupt ne elegantere Methode als es einfach aufzusplitten in 2 Anweisungen?
Das ist die falsche Frage, zumal der Umweg über float - wie schon gesagt - keine Lösung darstellt. Die Frage ist eher, warum du überhaupt ein Ergebnis, dass im Regelfall nicht exakt als Integer darstellbar ist, in ein int schreiben willst - oder ob du nicht von vornherein nur einen gerundeten Wert erhalten möchtest. In letzterem Falle muss die Frage dann lautet, wie man richtig rundet, und ein cast nach int schneidet einfach Nachkommastellen ab, rundet also immer in Richtung 0, was im Allgemeinen nicht das gewünschte Verhalten ist.
Wenn keine Besonderheiten vorliegen, solltedouble f = ... int i = static_cast< int >( floor( f + .5 ) );das gewünschte Ergbnis bewirken = aufrunden bei 0.5 (betragsmäßiges abrunden bei negativen Zahlen). Falls negative Zahlen nicht vorkommen, kann man auf das floor auch verzichten.
-
Hm, find ich grad doch bissel ätzend (an C++), dass man wegen so was trivialem wieder rumfrickeln muss.
Habs gerade mit C# getestet, und da gibt der Einzeiler auch ohne floor gefummel einfach 10, wie es auch sein sollte.
Naja, dennoch danke für die Antworten. :xmas1:
-
this->that schrieb:
Hm, find ich grad doch bissel ätzend (an C++), dass man wegen so was trivialem wieder rumfrickeln muss.
Habs gerade mit C# getestet, und da gibt der Einzeiler auch ohne floor gefummel einfach 10, wie es auch sein sollte.Nichts davon hat irgendetwas mit den Gründen zu tun, weswegen dieses Unterforum existiert. Bitte verschwende hier nicht deine und unsere Zeit mit derartigen Bemerkungen.
-
camper schrieb:
this->that schrieb:
Hm, find ich grad doch bissel ätzend (an C++), dass man wegen so was trivialem wieder rumfrickeln muss.
Habs gerade mit C# getestet, und da gibt der Einzeiler auch ohne floor gefummel einfach 10, wie es auch sein sollte.Nichts davon hat irgendetwas mit den Gründen zu tun, weswegen dieses Unterforum existiert. Bitte verschwende hier nicht deine und unsere Zeit mit derartigen Bemerkungen.
Musst doch nicht gleich weinen, nur weil ich mal C++ kritisiert habe.
