Nehmen wir an, ich habe einen Wert von 3,4679 und möchte 3,46. Wie kann ich das auf zwei Dezimalstellen kürzen, ohne aufzurunden?
Ich habe folgendes versucht, aber alle drei geben mir 3,47:
void Main()
{
Console.Write(Math.Round(3.4679, 2,MidpointRounding.ToEven));
Console.Write(Math.Round(3.4679, 2,MidpointRounding.AwayFromZero));
Console.Write(Math.Round(3.4679, 2));
}
Dies gibt 3,46 zurück, scheint aber nur ein bisschen schmutzig zu sein wie:
void Main()
{
Console.Write(Math.Round(3.46799999999 -.005 , 2));
}
Es wäre nützlicher, eine vollständige Funktion für die reale Verwendung des Abschneidens einer Dezimalstelle in C # zu haben. Dies könnte ziemlich einfach in eine Dezimalerweiterungsmethode konvertiert werden, wenn Sie möchten:
Wenn Sie VB.NET benötigen, versuchen Sie Folgendes:
Dann benutze es so:
oder
quelle
Verwenden Sie den Moduloperator:
Ergebnis: 0,54
quelle
Universelle und schnelle Methode (ohne
Math.Pow()
/ Multiplikation) fürSystem.Decimal
:quelle
Ein Problem bei den anderen Beispielen ist, dass sie den Eingabewert multiplizieren, bevor sie geteilt werden. Hier gibt es einen Kantenfall, bei dem Sie die Dezimalzahl überlaufen können, indem Sie zuerst einen Kantenfall multiplizieren, aber etwas, auf das ich gestoßen bin. Es ist sicherer, den Bruchteil wie folgt separat zu behandeln:
quelle
Ich werde die Lösung für Dezimalzahlen verlassen.
Einige der Lösungen für Dezimalstellen hier neigen zum Überlaufen (wenn wir eine sehr große Dezimalzahl übergeben und die Methode versucht, sie zu multiplizieren).
Die Lösung von Tim Lloyd ist vor Überlauf geschützt, aber nicht zu schnell.
Die folgende Lösung ist ungefähr zweimal schneller und hat kein Überlaufproblem:
quelle
Truncate
Methode wird zusammen mit nativen .net-Methoden unterstützt , sodass der Benutzer eine nahtlose Benutzererfahrung erhält.Assert.AreEqual(1.1m, 1.12m.TruncateEx(1));
scheitert daran. Wenn Sie im Math.Round-Aufruf "normale" Rundung (AwayFromZero) angeben,Assert.AreEqual(0m, 0m.TruncateEx(1));
schlägt dies fehlMidpointRounding.AwayFromZero
den Wert 0 verwenden und speziell codieren, um ihn zu verarbeiten.Dies ist eine alte Frage, aber viele Antworten funktionieren bei großen Zahlen nicht gut oder laufen nicht über. Ich denke, die Antwort von D. Nesterov ist die beste: robust, einfach und schnell. Ich möchte nur meine zwei Cent hinzufügen. Ich habe mit Dezimalstellen herumgespielt und auch den Quellcode überprüft . Aus der
public Decimal (int lo, int mid, int hi, bool isNegative, byte scale)
Konstruktordokumentation .In diesem Wissen bestand mein erster Ansatz darin, eine andere zu erstellen,
decimal
deren Skalierung den Dezimalstellen entspricht, die ich verwerfen wollte, sie dann abzuschneiden und schließlich eine Dezimalstelle mit der gewünschten Skalierung zu erstellen.Diese Methode ist nicht schneller als die von D. Nesterov und komplexer, also habe ich ein bisschen mehr herumgespielt. Ich vermute, dass
decimal
es langsamer wird, wenn man ein Auxiliar erstellen und die Bits zweimal abrufen muss. Bei meinem zweiten Versuch habe ich die von der Decimal.GetBits (Decimal d) -Methode zurückgegebenen Komponenten selbst manipuliert . Die Idee ist, die Komponenten so oft wie nötig durch 10 zu teilen und den Maßstab zu reduzieren. Der Code basiert (stark) auf der Methode Decimal.InternalRoundFromZero (ref Decimal d, int decimalCount) .Ich habe keine strengen Leistungstests durchgeführt, aber auf einem MacOS Sierra 10.12.6, 3.06 GHz Intel Core i3-Prozessor und Targeting .NetCore 2.1 scheint diese Methode viel schneller zu sein als die von D. Nesterov (ich werde seitdem keine Zahlen mehr angeben Wie bereits erwähnt, sind meine Tests nicht streng. Es liegt an jedem, der dies implementiert, zu bewerten, ob sich die Leistungssteigerungen für die zusätzliche Codekomplexität auszahlen oder nicht.
quelle
würde das für dich funktionieren?
quelle
Würden Sie
((long)(3.4679 * 100)) / 100.0
geben, was Sie wollen?quelle
Hier ist eine Erweiterungsmethode:
quelle
Wenn Sie sich nicht zu viele Sorgen um die Leistung machen und Ihr Endergebnis eine Zeichenfolge sein kann, ist der folgende Ansatz für Probleme mit schwebender Genauigkeit unempfindlich:
quelle
Hier ist meine Implementierung der TRUNC-Funktion
quelle
was ist damit?
quelle
Abgesehen von den oben genannten Lösungen gibt es noch einen anderen Weg, den wir erreichen können.
quelle
Unter bestimmten Umständen kann dies ausreichen.
Ich hatte einen Dezimalwert von SubCent = 0,0099999999999999999999999999M , der dazu neigt, auf | SubCent: 0,010000 | zu formatieren über
string.Format("{0:N6}", SubCent );
und viele andere Formatierungsoptionen.Meine Anforderung war nicht, den SubCent-Wert zu runden, sondern auch nicht jede Ziffer zu protokollieren.
Folgendes erfüllte meine Anforderung:
Was die Zeichenfolge zurückgibt: | SubCent: 0.0099999 |
Um den Wert mit einem ganzzahligen Teil aufzunehmen, ist das Folgende ein Anfang.
Welches gibt die Zeichenfolge zurück:
quelle
Ich benutze diese Funktion, um Wert nach Dezimalstelle in einer Zeichenfolgenvariablen abzuschneiden
quelle
Das habe ich getan:
Subtrahieren von zwei eingegebenen Zahlen, ohne die Dezimalstellen auf- oder abzurunden. weil die anderen Lösungen bei mir nicht funktionieren. Ich weiß nicht, ob es für andere funktionieren wird, ich möchte dies nur teilen :) Ich hoffe, es funktioniert auch für diejenigen, die eine Lösung für ein ähnliches Problem wie ich finden. Vielen Dank
PS: Ich bin ein Anfänger, also zögern Sie nicht, darauf hinzuweisen. : D Das ist gut, wenn Sie tatsächlich mit Geld zu tun haben, wegen der Cent, oder? Es hat nur 2 Dezimalstellen und die Rundung ist ein Nein Nein.
quelle
quelle
Eigentlich willst du 3.46 von 3.4679. Dies ist nur eine Darstellung von Zeichen. Es gibt also nichts mit der mathematischen Funktion zu tun. Die Math-Funktion ist nicht für diese Arbeit vorgesehen. Verwenden Sie einfach den folgenden Code.
quelle
wie wäre es mit
quelle