einen Dezimalwert in C ++ trunkieren
Frage
Was ist der einfachste Weg, um eine C ++ float
Variable gestutzt, der einen Wert von 0,6000002 auf einen Wert von 0,6000 hat und speichern Sie es zurück in die Variable?
Lösung
Zunächst ist es wichtig zu wissen, dass Gleitkommazahlen angenähert werden. Siehe den von @ Greg Hewgill angegebenen Link zu verstehen, warum dieses Problem nicht vollständig auflösbar ist.
Aber hier sind ein paar Lösungen für das Problem, die Ihren Bedarf wahrscheinlich treffen werden:
Wahrscheinlich die bessere Methode ist aber weniger effizient:
char sz[64];
double lf = 0.600000002;
sprintf(sz, "%.4lf\n", lf); //sz contains 0.6000
double lf2 = atof(sz);
//lf == 0.600000002;
//lf2 == 0.6000
printf("%.4lf", lf2); //print 0.6000
Die effizientere Art und Weise, aber wahrscheinlich weniger genau:
double lf = 0.600000002;
int iSigned = lf > 0? 1: -1;
unsigned int uiTemp = (lf*pow(10, 4)) * iSigned; //Note I'm using unsigned int so that I can increase the precision of the truncate
lf = (((double)uiTemp)/pow(10,4) * iSigned);
Andere Tipps
Eine gute Referenz für Warum dies geschieht, kann unter
Realistisch betrachtet, das ist nicht möglich. Es ist kein C ++ Einschränkung, sondern nur die Art und Weise Floating-Point arbeitet. Für viele Werte gibt es keine genauen Darstellungen, so können Sie einfach nicht auf eine Anzahl von Stellen gestutzt. Sie kürzen können, wenn Strings mit printf Formatdruck. Wenn Sie wirklich in der Lage sein müssen, nur eine begrenzte Anzahl von Ziffern zu speichern, ich schlage vor, Sie verwenden einen feste genauen Datentyp statt.
Ich denke, die Frage, die hier gestellt werden soll ist: Warum brauchen Sie es abgeschnitten?
Wenn sein für einen Vergleich zwischen den Werten, sollten Sie vielleicht mit dem Epsilon-Test prüfen. (Mit einem zusätzlichen Toleranzwert, in Ihrem Fall, da es viel größer ist als das allgemein akzeptierte epsilon zu sein scheint).
Wenn Sie wollen es einfach als 0,6000 auszudrucken, verwenden Sie die Methoden andere vorgeschlagen haben.
roundf(myfloat * powf(10, numDigits)) / powf(10, numDigits);
Zum Beispiel, in Ihrem Fall Sie Kürzen drei Ziffern (numDigits). Sie würden verwenden:
roundf(0.6000002 * 1000) / 1000
// And thus:
roundf(600.0002) / 1000
600 / 1000
0.6
(Sie würde wahrscheinlich das Ergebnis von powf speichern irgendwo, da Sie es zweimal verwenden.)
Aufgrund wie Schwimmer sind normalerweise auf Computern gespeichert, würde es wahrscheinlich Ungenauigkeiten sein. Das ist, was Sie für die Verwendung von Schwimmern bekommen, though.
verwenden:
floor(0.6000002*10000)/10000
Für C 11 ++ Sie std::round
definiert in Header <cmath>
verwenden können:
auto trunc_value = std::round(value_to_trunc * 10000) / 10000;
Hier ist eine Funktion, die Beratung in anderen Antworten und ein Beispiel für die Verwendung mit:
#include <iostream>
#include <cmath>
static void Truncate(double& d, unsigned int numberOfDecimalsToKeep);
int main(int, char*[])
{
double a = 1.23456789;
unsigned int numDigits = 3;
std::cout << a << std::endl;
Truncate(a,3);
std::cout << a << std::endl;
return 0;
}
void Truncate(double& d, unsigned int numberOfDecimalsToKeep)
{
d = roundf(d * powf(10, numberOfDecimalsToKeep)) / powf(10, numberOfDecimalsToKeep);
}
Ähnlich wie bei anderen Antworten, aber Sie müssen diese Runde nicht vergessen, Boden und trunc definitionsgemäß unterschiedlich sind. Siehe die Definition und Ausgabebeispiel der folgenden Optionen:
http://www.cplusplus.com/reference/cmath/trunc/
In diesem Fall müssen wir mit einer Genauigkeit von 4 Dezimalstellen trucate und loszuwerden nicht-signifikanter Dezimalstellen:
trunc(valueToTrunc*10000)/10000
oder
value = (double)((int)(valueToTrunc*10000))/(double)10000