2,50 ist nur 2,5. Ich nehme an, Sie sprechen von Saiten.
Tim Schmelter
3
Geben Sie immer die ersten beiden Ziffern nach der Dezimalstelle zurück? Ist die Eingabe ein decimal, float, string, ...?
Greg
3
Ein Beispiel für die Verwendung trägt wesentlich dazu bei, für das nächste Mal qualitativ hochwertige Antworten zu erhalten.
tmesser
ja nur zwei Ziffern, die Eingabe ist dezimal
user1095549
3
Dem C # -Entwicklungsteam sollte es peinlich sein (und Maßnahmen ergreifen), dass diese sehr häufige Operation keine einzelne Math.-Funktion wie Math.DecimalPart (double x) oder ähnliches hat. Es gibt viel zu viel "Hast du das versucht, hast du darüber nachgedacht" für etwas, das viele von uns oft tun müssen.
Wenn dies nicht das erwartete Ergebnis ist, müssen Sie das Ergebnis in die gewünschte Form ändern (aber Sie können möglicherweise einige Zeichenfolgenmanipulationen erneut durchführen.)
[2] unter Verwendung eines Multiplikators [der 10 hoch N (z. B. 10² oder 10³) ist, wobei N die Anzahl der Dezimalstellen ist]
// multiplier is " 10 to the power of 'N'" where 'N' is the number // of decimal placesint multiplier = 1000;
double double_value = 12.345;
int double_result = (int)((double_value - (int)double_value) * multiplier);
// Ausgabe 345
Wenn die Anzahl der Dezimalstellen nicht festgelegt ist, kann dieser Ansatz zu Problemen führen.
[3] Verwenden von "Regular Expressions (REGEX)"
Wir sollten sehr vorsichtig sein, wenn wir Lösungen mit String schreiben. Dies wäre außer in einigen Fällen nicht vorzuziehen .
Wenn Sie einige Zeichenfolgenoperationen mit Dezimalstellen ausführen möchten, ist dies vorzuziehen
string input_decimal_number = "1.50";
var regex = new System.Text.RegularExpressions.Regex("(?<=[\\.])[0-9]+");
if (regex.IsMatch(input_decimal_number))
{
string decimal_places = regex.Match(input_decimal_number).Value;
}
Seien Sie vorsichtig mit ToString (), da für ganze Zahlen keine Dezimalstellen zurückgegeben werden. Wenn MyValue 3 ist, gibt MyValue.ToString () "3" zurück, sodass Split ('.') [1] ausgelöst wird. Geben Sie das Format explizit auf die Anzahl der benötigten Dezimalstellen an: MyValue.ToString ("F2"). Split ('.') [1]
Alex Beynenson
7
Diese Lösung ist ungefähr zwei Größenordnungen langsamer als jede andere Lösung auf dieser Seite und vier Größenordnungen langsamer als meine eigene Antwort.
Messer
1
Diese Lösung ist kulturspezifisch. Beispielsweise gibt es in Russisch und Englisch-USA unterschiedliche Dezimaltrennzeichen (Komma und Punkt entsprechend). Dieser Code schlägt also in anderen Kulturen fehl.
Yury Schkatula
2
Diese Lösung teilt sich auf das ., was nicht immer das Dezimaltrennzeichen ist (dh in Europa ist das Dezimaltrennzeichen ,). Sie müssen hinzufügen CultureInfo.Invariant, um es international zu machen. Obwohl es einfacher ist, x - Math.Truncate(x)dieses Ergebnis zu verwenden und zu zaubern.
Dies sollte die akzeptierte Antwort sein, eine mathematische Lösung für eine mathematische Frage, ohne all das mühsame
Herumspielen
19
Ich denke, diese Lösung hat ein "Problem". Wenn die floatNumber "10.2" war, ist die Variable x ungefähr "0.19999999999999929". Selbst wenn dies wie erwartet funktioniert, wäre das Ergebnis "0,2" und nicht "2".
Dherik
4
@Dherik Float- und Double-Werte weisen bei Subtraktion auf den letzten Dezimalstellen immer kleine Fehler auf. Sie sollten diese nicht als wichtig betrachten. Wenn Sie diese Genauigkeit tatsächlich benötigen, sollten Sie den Dezimaltyp verwenden. Wenn Sie nicht zu Dezimal wechseln können (oder einfach nicht wollen), sollten Sie die erwartete Genauigkeit irgendwie im Auge behalten und dies bei Vergleichsoperationen berücksichtigen. Normalerweise verwende ich 4 Dezimalstellen, aber es kann Ausnahmen geben.
Philologon
Aus msdn.microsoft.com/en-us/library/… : "Da einige Zahlen nicht genau als gebrochene Binärwerte dargestellt werden können, können Gleitkommazahlen nur reelle Zahlen approximieren"
Philologon
1
Abschließender Kommentar: Die Verwendung von Math.Truncate war die Absicht des Autors der Math-Bibliothek für diese Art von Situation. Die Antwort von @Matterai sollte die akzeptierte sein.
Philologon
80
var decPlaces = (int)(((decimal)number % 1) * 100);
Dies setzt voraus, dass Ihre Zahl nur zwei Dezimalstellen hat.
(318.40d % 1) * 100Ausgaben 39.9999999999977können Sie Casting verwenden, um den Rundungsfehler zu var decPlaces = (int)(((decimal)number % 1) * 100);
umgehen
@orad Guter Anruf dort - Gleitkommazahlen weisen immer diese kleinen Ungenauigkeiten auf, daher ist es ziemlich umsichtig, ein konsistentes Verhalten sicherzustellen. Ich werde meine Antwort aktualisieren, obwohl Matterais technisch noch korrekter ist.
Messer
26
Es gibt eine sauberere und schnellere Lösung als den "Math.Truncate" -Ansatz:
ein Hinweis: für negative Werte ist es negativ : -12,34% 1 => -0,33999999999999986
Alex Poca
15
Lösung ohne Rundungsproblem:
double number = 10.20;
var first2DecimalPlaces = (int)(((decimal)number % 1) * 100);
Console.Write("{0:00}", first2DecimalPlaces);
Ausgänge:20
Beachten Sie, dass die Ausgabe nicht dezimal erfolgt 19.
Ebenfalls:
für 318.40Ausgänge: 40(anstelle von 39)
für 47.612345Ausgänge: 61(anstelle von 612345)
für 3.01Ausgänge: 01(anstelle von 1)
Wenn Sie mit Finanzzahlen arbeiten, z. B. wenn Sie in diesem Fall versuchen, den Cent- Teil eines Transaktionsbetrags zu erhalten, verwenden Sie immer den decimalDatentyp.
Aktualisieren:
Das Folgende funktioniert auch, wenn es als Zeichenfolge verarbeitet wird (basierend auf der Antwort von @ SearchForKnowledge).
Die Frage ist, die ersten 2 Dezimalstellen zu erhalten. Für die Anzahl 318.401567dIhrer Lösungsausgaben, 0.401567wo 40erwartet wird.
Orad
0
publicstaticstringFractionPart(thisdouble instance)
{
var result = string.Empty;
var ic = CultureInfo.InvariantCulture;
var splits = instance.ToString(ic).Split(new[] { ic.NumberFormat.NumberDecimalSeparator }, StringSplitOptions.RemoveEmptyEntries);
if (splits.Count() > 1)
{
result = splits[1];
}
return result;
}
Hier ist eine Erweiterungsmethode, die ich für eine ähnliche Situation geschrieben habe. Meine Bewerbung würde Zahlen im Format 2,3 oder 3,11 erhalten, wobei die ganzzahlige Komponente der Zahl Jahre und die gebrochene Komponente Monate darstellt.
// Sample Usageint years, months;
double test1 = 2.11;
test1.Split(out years, out months);
// years = 2 and months = 11publicstaticclassDoubleExtensions
{
publicstaticvoidSplit(thisdouble number, outint years, outint months)
{
years = Convert.ToInt32(Math.Truncate(number));
double tempMonths = Math.Round(number - years, 2);
while ((tempMonths - Math.Floor(tempMonths)) > 0 && tempMonths != 0) tempMonths *= 10;
months = Convert.ToInt32(tempMonths);
}
}
Sie können den Punkt .aus dem Doppel entfernen, bei dem Sie versuchen, die Dezimalstellen aus der Verwendung von zu erhaltenRemove() Funktion zu nachdem Sie das Double in einen String konvertiert haben, damit Sie die erforderlichen Operationen ausführen können
Wenn Sie einen doppelten _DoubleWert von haben 0.66781, zeigt der folgende Code nur die Zahlen nach dem Punkt an, .die sind66781
double _Double = 0.66781; //Declare a new double with a value of 0.66781string _Decimals = _Double.ToString().Remove(0, _Double.ToString().IndexOf(".") + 1); //Remove everything starting with index 0 and ending at the index of ([the dot .] + 1)
Eine andere Lösung
Sie können auch die Klasse verwenden, die Pathplattformübergreifend Operationen an Zeichenfolgeninstanzen ausführt
double _Double = 0.66781; //Declare a new double with a value of 0.66781string Output = Path.GetExtension(D.ToString()).Replace(".",""); //Get (the dot and the content after the last dot available and replace the dot with nothing) as a new string object Output//Do something
Nicht sehr beliebt bei, Regex.Matchaber ich habe den folgenden Fehler erhalten, als ich versucht habe, den Wert der Dezimalstelle zu erhaltenArgumentException was unhandled: parsing "\.(?\d+)" - Unrecognized grouping construct.
Picrofo Software
-2
Es ist sehr einfach
float moveWater = Mathf.PingPong(theTime * speed, 100) * .015f;
int m = (int)(moveWater);
float decimalPart= moveWater -m ;
Debug.Log(decimalPart);
Dies wird funktionieren:Int32.Parse((12.05123d.ToString("0.00").Split('.')[1]))
Orad
Weil Sie es in eine Zeichenfolge umwandeln, um eine Zeichenfolgenmanipulation durchzuführen. Ich glaube nicht, dass Sie erkennen, wie langsam und verschwenderisch das ist.
decimal
,float
,string
, ...?Antworten:
Aktualisierte Antwort
Hier gebe ich 3 Ansätze für das gleiche.
[1] Math Solution mit Math.Truncate
var float_number = 12.345; var result = float_number - Math.Truncate(float_number);
// Eingabe: 1.05
// Ausgabe: "0.050000000000000044"
// Eingabe: 10.2
// Ausgabe: 0.19999999999999929
Wenn dies nicht das erwartete Ergebnis ist, müssen Sie das Ergebnis in die gewünschte Form ändern (aber Sie können möglicherweise einige Zeichenfolgenmanipulationen erneut durchführen.)
[2] unter Verwendung eines Multiplikators [der 10 hoch N (z. B. 10² oder 10³) ist, wobei N die Anzahl der Dezimalstellen ist]
// multiplier is " 10 to the power of 'N'" where 'N' is the number // of decimal places int multiplier = 1000; double double_value = 12.345; int double_result = (int)((double_value - (int)double_value) * multiplier);
// Ausgabe 345
Wenn die Anzahl der Dezimalstellen nicht festgelegt ist, kann dieser Ansatz zu Problemen führen.
[3] Verwenden von "Regular Expressions (REGEX)"
Wir sollten sehr vorsichtig sein, wenn wir Lösungen mit String schreiben. Dies wäre außer in einigen Fällen nicht vorzuziehen .
Wenn Sie einige Zeichenfolgenoperationen mit Dezimalstellen ausführen möchten, ist dies vorzuziehen
string input_decimal_number = "1.50"; var regex = new System.Text.RegularExpressions.Regex("(?<=[\\.])[0-9]+"); if (regex.IsMatch(input_decimal_number)) { string decimal_places = regex.Match(input_decimal_number).Value; }
// Eingabe: "1.05"
// Ausgabe: "05"
// Eingabe: "2.50"
// Ausgabe: "50"
// Eingabe: "0.0550"
// Ausgabe: "0550"
Weitere Informationen zu Regex finden Sie unter http://www.regexr.com/.
quelle
.
, was nicht immer das Dezimaltrennzeichen ist (dh in Europa ist das Dezimaltrennzeichen,
). Sie müssen hinzufügenCultureInfo.Invariant
, um es international zu machen. Obwohl es einfacher ist,x - Math.Truncate(x)
dieses Ergebnis zu verwenden und zu zaubern.Das Beste vom Besten ist:
var floatNumber = 12.5523; var x = floatNumber - Math.Truncate(floatNumber);
Ergebnis können Sie konvertieren, wie Sie möchten
quelle
var decPlaces = (int)(((decimal)number % 1) * 100);
Dies setzt voraus, dass Ihre Zahl nur zwei Dezimalstellen hat.
quelle
(318.40d % 1) * 100
Ausgaben39.9999999999977
können Sie Casting verwenden, um den Rundungsfehler zuvar decPlaces = (int)(((decimal)number % 1) * 100);
Es gibt eine sauberere und schnellere Lösung als den "Math.Truncate" -Ansatz:
double frac = value % 1;
quelle
Lösung ohne Rundungsproblem:
double number = 10.20; var first2DecimalPlaces = (int)(((decimal)number % 1) * 100); Console.Write("{0:00}", first2DecimalPlaces);
Ausgänge:
20
Ebenfalls:
318.40
Ausgänge:40
(anstelle von39
)47.612345
Ausgänge:61
(anstelle von612345
)3.01
Ausgänge:01
(anstelle von1
)Aktualisieren:
Das Folgende funktioniert auch, wenn es als Zeichenfolge verarbeitet wird (basierend auf der Antwort von @ SearchForKnowledge).
10.2d.ToString("0.00", CultureInfo.InvariantCulture).Split('.')[1]
Sie können es dann verwenden
Int32.Parse
, um es in int zu konvertieren.quelle
Besserer Weg -
double value = 10.567; int result = (int)((value - (int)value) * 100); Console.WriteLine(result);
Ausgabe -
56
quelle
10.20
es wird ausgegeben19
. Siehe meine Antwort.Die einfachste Variante ist möglicherweise mit Math.truncate ()
double value = 1.761 double decPart = value - Math.truncate(value)
quelle
Ich denke, dieser Thread wird alt, aber ich kann nicht glauben, dass niemand Math.Floor erwähnt hat
//will always be .02 cents (10.02m - System.Math.Floor(10.02m))
quelle
double fract(double x) { return x - System.Math.Floor(x); }
var result = number.ToString().Split(System.Globalization.NumberDecimalSeparator)[2]
Gibt es als Zeichenfolge zurück (aber Sie können es jederzeit in ein int umwandeln) und nimmt an, dass die Zahl ein "." irgendwo.
quelle
int last2digits = num - (int) ((double) (num / 100) * 100);
quelle
318.401567d
Ihrer Lösungsausgaben,0.401567
wo40
erwartet wird.public static string FractionPart(this double instance) { var result = string.Empty; var ic = CultureInfo.InvariantCulture; var splits = instance.ToString(ic).Split(new[] { ic.NumberFormat.NumberDecimalSeparator }, StringSplitOptions.RemoveEmptyEntries); if (splits.Count() > 1) { result = splits[1]; } return result; }
quelle
Hier ist eine Erweiterungsmethode, die ich für eine ähnliche Situation geschrieben habe. Meine Bewerbung würde Zahlen im Format 2,3 oder 3,11 erhalten, wobei die ganzzahlige Komponente der Zahl Jahre und die gebrochene Komponente Monate darstellt.
// Sample Usage int years, months; double test1 = 2.11; test1.Split(out years, out months); // years = 2 and months = 11 public static class DoubleExtensions { public static void Split(this double number, out int years, out int months) { years = Convert.ToInt32(Math.Truncate(number)); double tempMonths = Math.Round(number - years, 2); while ((tempMonths - Math.Floor(tempMonths)) > 0 && tempMonths != 0) tempMonths *= 10; months = Convert.ToInt32(tempMonths); } }
quelle
Das kann Overhead sein, sollte aber funktionieren.
double yourDouble = 1.05; string stringForm = yourDouble.ToString(); int dotPosition = stringForm.IndexOf("."); decimal decimalPart = Decimal.Parse("0" + stringForm.Substring(dotPosition)); Console.WriteLine(decimalPart); // 0.05
quelle
Sie können den Punkt
.
aus dem Doppel entfernen, bei dem Sie versuchen, die Dezimalstellen aus der Verwendung von zu erhaltenRemove()
Funktion zu nachdem Sie das Double in einen String konvertiert haben, damit Sie die erforderlichen Operationen ausführen könnenWenn Sie einen doppelten
_Double
Wert von haben0.66781
, zeigt der folgende Code nur die Zahlen nach dem Punkt an,.
die sind66781
double _Double = 0.66781; //Declare a new double with a value of 0.66781 string _Decimals = _Double.ToString().Remove(0, _Double.ToString().IndexOf(".") + 1); //Remove everything starting with index 0 and ending at the index of ([the dot .] + 1)
Eine andere Lösung
Sie können auch die Klasse verwenden, die
Path
plattformübergreifend Operationen an Zeichenfolgeninstanzen ausführtdouble _Double = 0.66781; //Declare a new double with a value of 0.66781 string Output = Path.GetExtension(D.ToString()).Replace(".",""); //Get (the dot and the content after the last dot available and replace the dot with nothing) as a new string object Output //Do something
quelle
Verwenden Sie eine Regex:
Regex.Match("\.(?\d+)")
Jemand korrigiert mich, wenn ich hier falsch liegequelle
Regex.Match
aber ich habe den folgenden Fehler erhalten, als ich versucht habe, den Wert der Dezimalstelle zu erhaltenArgumentException was unhandled: parsing "\.(?\d+)" - Unrecognized grouping construct.
Es ist sehr einfach
float moveWater = Mathf.PingPong(theTime * speed, 100) * .015f; int m = (int)(moveWater); float decimalPart= moveWater -m ; Debug.Log(decimalPart);
quelle
Warum nicht verwenden
int y = value.Split('.')[1];
?Die
Split()
Funktion teilt den Wert in separaten Inhalt auf und1
gibt den 2. Wert nach dem aus.
quelle
Int32.Parse((12.05123d.ToString("0.00").Split('.')[1]))