Wie runde ich einen Dezimalwert auf 2 Dezimalstellen (für die Ausgabe auf einer Seite)?

647

Wenn der aktuelle Wert einer Dezimalstelle mit angezeigt wird .ToString(), entspricht dies genau 15 Dezimalstellen. Da ich damit Dollar und Cent darstelle, möchte ich, dass die Ausgabe nur 2 Dezimalstellen beträgt.

Benutze ich dafür eine Variation von .ToString()?

wows
quelle

Antworten:

909
decimalVar.ToString ("#.##"); // returns "" when decimalVar == 0

oder

decimalVar.ToString ("0.##"); // returns "0"  when decimalVar == 0
Albertein
quelle
31
Das Problem hier ist, wenn wir 0,00 haben; es gibt eine leere Zeichenfolge zurück.
Jronny
164
Dann könnten Sie decimalVar.ToString ("0. ##") ausführen. Sie können auch 0.00 als Formatierungszeichenfolge verwenden.
Albertein
54
Mit dieser Lösung haben Sie nicht die Kulturformatierung, die Sie beim Lesen von Zahlen erwarten würden. Verwenden Sie dazu ToString ("N2") oder ToString ("N").
Shautieh
2
Die Methode @Hill Decimaland Doubletype ToStringakzeptiert Argumente für die Formatierung. Konvertieren Sie zuerst Ihren Wert in Decimal / Double.
Sohaiby
1
@ f470071 Dezimalstellen sind Werttypen und werden als solche niemals "geändert". Unabhängig davon wurde von ToString () nie erwartet, dass es den Inhalt dessen ändert, was auch immer aufgerufen wird.
Justin Skiles
588

Ich weiß, dass dies eine alte Frage ist, aber ich war überrascht zu sehen, dass niemand eine Antwort darauf zu posten schien;

  1. Ich habe keine Banker verwendet
  2. Der Wert wurde nicht als Dezimalzahl beibehalten.

Dies ist, was ich verwenden würde:

decimal.Round(yourValue, 2, MidpointRounding.AwayFromZero);

http://msdn.microsoft.com/en-us/library/9s0xa85y.aspx

Mike M.
quelle
3
ToString oder string.Format verwenden keine Banker-Rundung: msdn.microsoft.com/en-us/library/0c899ak8.aspx#sectionToggle1
Matthijs Wessels
1
@MatthijsWessels Ich weiß ... aber der Wert wird auch nicht als Dezimalzahl beibehalten.
Mike M.
1
Dies ist eine bessere Möglichkeit, zwei Dezimalstellen wirklich darzustellen, da keine nachgestellten Nullen gelöscht werden.
LiquidDrummer
353
decimalVar.ToString("F");

Dieser Wille:

  • Auf 2 Dezimalstellen abrunden, z. 23.45623.46
  • Stellen Sie sicher, dass immer 2 Dezimalstellen vorhanden sind, z. 2323.00; 12.512.50

Ideal zum Anzeigen von Währungen.

Lesen Sie die Dokumentation zu ToString ("F") (danke an Jon Schneider).

Sofox
quelle
10
Dies funktioniert gut, wenn nur 1 Dezimalstelle vorhanden ist. .ToString ("#. ##") schlägt fehl. Diese Antwort ist viel besser
Eric Frick
2
Wäre es nicht rund 23.456 => 23.46?
RTPHarry
14
Dokumentation darüber, was das "F" hier bedeutet und wie es funktioniert: msdn.microsoft.com/en-us/library/…
Jon Schneider
4
Warum nicht .ToString ("N") anstelle von "F"? Ich verstehe, dass beide für die Anforderungen dieser Frage arbeiten werden, aber N wird auch Kommas für Zahlen zu Tausenden eingeben.
Jgerman
Hinweis: Das .kann ,aufgrund der Kultur durch ersetzt werden. Sie sollten CultureInfo.InvariantCultureals zweites Argument angeben, um dies zu deaktivieren.
Duncan Luk
106

Wenn Sie dies nur für die Anzeige benötigen, verwenden Sie string.Format

String.Format("{0:0.00}", 123.4567m);      // "123.46"

http://www.csharp-examples.net/string-format-double/

Das "m" ist ein Dezimalsuffix. Über das Dezimalsuffix:

http://msdn.microsoft.com/en-us/library/364x0z75.aspx

Jorge Ferreira
quelle
10
Technisch gesehen wäre es für eine Dezimalstelle 123,4567 m, ja? Ohne das Suffix "m" ist es ein Doppel
Adam Tegen
2
oder Verknüpfung $ "{Wert: 0,00}"
mamczas
56

Gegebene Dezimalstelle d = 12,345; Die Ausdrücke d.ToString ("C") oder String.Format ("{0: C}", d) ergeben 12,35 USD. Beachten Sie, dass die Währungseinstellungen der aktuellen Kultur einschließlich des Symbols verwendet werden.

Beachten Sie, dass "C" die Anzahl der Ziffern aus der aktuellen Kultur verwendet. Sie können jederzeit außer Kraft setzen Standard notwendige Präzision zu zwingen , C{Precision specifier}wie String.Format("{0:C2}", 5.123d).

Hafthor
quelle
4
@ Slick86 - das aktuelle Zeichen
Fubo
48

Wenn Sie möchten, dass es mit Kommas sowie einem Dezimalpunkt (aber ohne Währungssymbol) formatiert wird, z. B. 3.456.789,12 ...

decimalVar.ToString("n2");
Joel Mueller
quelle
1
Bessere Antwort, da es um die Ausgabe auf einer Seite ging und die Formatierung der Zahlen für große Zahlen wichtig ist. Außerdem berücksichtigt "n *" die aktuelle Kultur, so dass es "3.456.789,12", "3 456 789,12" usw. sein kann
Shautieh
29

Es gibt bereits zwei Antworten mit hoher Punktzahl, die sich auf Decimal.Round (...) beziehen, aber ich denke, es ist etwas mehr Erklärung erforderlich - da es eine unerwartet wichtige Eigenschaft von Decimal gibt, die nicht offensichtlich ist.

Eine Dezimalstelle "weiß", wie viele Dezimalstellen sie hat, je nachdem, woher sie stammt.

Zum Beispiel kann Folgendes unerwartet sein:

Decimal.Parse("25").ToString()          =>   "25"
Decimal.Parse("25.").ToString()         =>   "25"
Decimal.Parse("25.0").ToString()        =>   "25.0"
Decimal.Parse("25.0000").ToString()     =>   "25.0000"

25m.ToString()                          =>   "25"
25.000m.ToString()                      =>   "25.000"

Wenn Sie dieselben Operationen mit ausführen, Doublewerden "25"für jede der oben genannten Optionen keine Dezimalstellen ( ) angegeben.

Wenn Sie eine Dezimalstelle mit 2 Dezimalstellen wünschen, liegt die Wahrscheinlichkeit bei 95%, weil es sich um eine Währung handelt. In diesem Fall ist dies wahrscheinlich in 95% der Fälle in Ordnung:

Decimal.Parse("25.0").ToString("c")     =>   "$25.00"

Oder in XAML verwenden Sie einfach {Binding Price, StringFormat=c}

Ein Fall, in dem ich eine Dezimalstelle als Dezimalzahl benötigte, war das Senden von XML an den Webservice von Amazon. Der Dienst hat sich beschwert, weil ein Dezimalwert (ursprünglich von SQL Server) als gesendet 25.1200und abgelehnt wurde ( 25.12war das erwartete Format).

Ich musste nur Decimal.Round(...)2 Dezimalstellen verwenden, um das Problem zu beheben.

 // This is an XML message - with generated code by XSD.exe
 StandardPrice = new OverrideCurrencyAmount()
 {
       TypedValue = Decimal.Round(product.StandardPrice, 2),
       currency = "USD"
 }

TypedValueist vom Typ, Decimalalso konnte ich es nicht einfach tun ToString("N2")und musste es abrunden und als behalten decimal.

Simon_Weaver
quelle
5
+1 das ist eine gute Antwort. Wenn Sie sagen, dass System.Decimal "weiß, wie viele Dezimalstellen vorhanden sind", bedeutet dies, dass sich System.Decimal nicht wie die anderen Gleitkommatypen selbst normalisiert . Eine weitere nützliche Eigenschaft von System.Decimal ist, dass das Ergebnis von mathematischen Operationen immer die höchste Anzahl von Dezimalstellen aus den Eingabeargumenten aufweist, d. H. 1,0 m + 2.000 m = 3.000 m . Sie können diese Tatsache verwenden, um eine Dezimalstelle ohne Dezimalstellen auf 2 Dezimalstellen zu zwingen, indem Sie sie einfach mit 1,00 m multiplizieren, z. 10 m * 1,00 m = 10,00 m .
MattDavey
2
MattDavey's ist falsch, die Dezimalgenauigkeit wird hinzugefügt. (1,0 m * 1,00 m) .ToString () = "1.000"
Kaido
2
Es ist sehr, sehr nützlich zu wissen, dass "eine Dezimalstelle 'weiß', wie viele Dezimalstellen sie hat, basierend darauf, woher sie stammt." Vielen Dank!
Iheartcsharp
21

Hier ist ein kleines Linqpad-Programm, um verschiedene Formate anzuzeigen:

void Main()
{
    FormatDecimal(2345.94742M);
    FormatDecimal(43M);
    FormatDecimal(0M);
    FormatDecimal(0.007M);
}

public void FormatDecimal(decimal val)
{
    Console.WriteLine("ToString: {0}", val);
    Console.WriteLine("c: {0:c}", val);
    Console.WriteLine("0.00: {0:0.00}", val);
    Console.WriteLine("0.##: {0:0.##}", val);
    Console.WriteLine("===================");
}

Hier sind die Ergebnisse:

ToString: 2345.94742
c: $2,345.95
0.00: 2345.95
0.##: 2345.95
===================
ToString: 43
c: $43.00
0.00: 43.00
0.##: 43
===================
ToString: 0
c: $0.00
0.00: 0.00
0.##: 0
===================
ToString: 0.007
c: $0.01
0.00: 0.01
0.##: 0.01
===================
Was wäre cool
quelle
15

Math.Round-Methode (Dezimal, Int32)

John Smith
quelle
Verwendet das nicht die Rundung des Bankiers?
Danimal
Dies ist der beste Weg, da der Wert nicht in eine Zeichenfolge konvertiert wird und Sie weiterhin mathematische Operationen ausführen können
Shinji14
@Danimal: Sie können ein drittes Argument liefern, um den Rundungstyp zu ändern
Jay Sullivan
11

Sehr selten möchten Sie eine leere Zeichenfolge, wenn der Wert 0 ist.

decimal test = 5.00;
test.ToString("0.00");  //"5.00"
decimal? test2 = 5.05;
test2.ToString("0.00");  //"5.05"
decimal? test3 = 0;
test3.ToString("0.00");  //"0.00"

Die am besten bewertete Antwort ist falsch und hat 10 Minuten (der meisten) Zeit verschwendet.

goamn
quelle
1
"#"bedeutet im Grunde Ziffer der Zahl (falls erforderlich) (ohne Auffüllen, wenn nicht benötigt) "0"bedeutet Ziffer der Zahl (
egal
10

Die Antwort von Mike M. war perfekt für mich in .NET, aber .NET Core hat decimal.Roundzum Zeitpunkt des Schreibens keine Methode.

In .NET Core musste ich Folgendes verwenden:

decimal roundedValue = Math.Round(rawNumber, 2, MidpointRounding.AwayFromZero);

Eine hackige Methode, einschließlich der Konvertierung in einen String, ist:

public string FormatTo2Dp(decimal myNumber)
{
    // Use schoolboy rounding, not bankers.
    myNumber = Math.Round(myNumber, 2, MidpointRounding.AwayFromZero);

    return string.Format("{0:0.00}", myNumber);
}
HockeyJ
quelle
9

Keiner von diesen hat genau das getan, was ich brauchte, um 2 dp zu erzwingen und als aufzurunden0.005 -> 0.01

Um 2 dp zu erzwingen, muss die Genauigkeit um 2 dp erhöht werden, um sicherzustellen, dass mindestens 2 dp vorhanden sind

dann runden, um sicherzustellen, dass wir nicht mehr als 2 dp haben

Math.Round(exactResult * 1.00m, 2, MidpointRounding.AwayFromZero)

6.665m.ToString() -> "6.67"

6.6m.ToString() -> "6.60"
Kaido
quelle
9

Die am besten bewertete Antwort beschreibt eine Methode zum Formatieren der Zeichenfolgendarstellung des Dezimalwerts und funktioniert.

Wenn Sie jedoch die gespeicherte Genauigkeit auf den tatsächlichen Wert ändern möchten, müssen Sie Folgendes schreiben:

public static class PrecisionHelper
{
    public static decimal TwoDecimalPlaces(this decimal value)
    {
        // These first lines eliminate all digits past two places.
        var timesHundred = (int) (value * 100);
        var removeZeroes = timesHundred / 100m;

        // In this implementation, I don't want to alter the underlying
        // value.  As such, if it needs greater precision to stay unaltered,
        // I return it.
        if (removeZeroes != value)
            return value;

        // Addition and subtraction can reliably change precision.  
        // For two decimal values A and B, (A + B) will have at least as 
        // many digits past the decimal point as A or B.
        return removeZeroes + 0.01m - 0.01m;
    }
}

Ein Beispiel für einen Unit-Test:

[Test]
public void PrecisionExampleUnitTest()
{
    decimal a = 500m;
    decimal b = 99.99m;
    decimal c = 123.4m;
    decimal d = 10101.1000000m;
    decimal e = 908.7650m

    Assert.That(a.TwoDecimalPlaces().ToString(CultureInfo.InvariantCulture),
        Is.EqualTo("500.00"));

    Assert.That(b.TwoDecimalPlaces().ToString(CultureInfo.InvariantCulture),
        Is.EqualTo("99.99"));

    Assert.That(c.TwoDecimalPlaces().ToString(CultureInfo.InvariantCulture),
        Is.EqualTo("123.40"));

    Assert.That(d.TwoDecimalPlaces().ToString(CultureInfo.InvariantCulture),
        Is.EqualTo("10101.10"));

    // In this particular implementation, values that can't be expressed in
    // two decimal places are unaltered, so this remains as-is.
    Assert.That(e.TwoDecimalPlaces().ToString(CultureInfo.InvariantCulture),
        Is.EqualTo("908.7650"));
}
Alex
quelle
7

Mit system.globalization können Sie eine Zahl in einem beliebigen Format formatieren.

Zum Beispiel:

system.globalization.cultureinfo ci = new system.globalization.cultureinfo("en-ca");

Wenn Sie eine haben decimal d = 1.2300000und diese auf 2 Dezimalstellen d.Tostring("F2",ci);kürzen müssen, kann sie wie folgt gedruckt werden, wobei F2 eine Zeichenfolge mit 2 Dezimalstellen ist und ci das Gebietsschema oder die Kulturinfo ist.

Weitere Informationen finden Sie unter folgendem Link:
http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx

Smitha Poluri
quelle
+1 aber - das CultureInfo-Objekt wirkt sich nur auf das Unicode-Zeichen aus, mit dem die Dezimalstelle angegeben wird. z.B. fr-FR würde ein Komma anstelle eines Punktes verwenden. Es hängt nicht mit der Anzahl der gerenderten Dezimalstellen zusammen.
MattDavey
4

https://msdn.microsoft.com/en-us/library/dwhawy9k%28v=vs.110%29.aspx

Dieser Link erklärt ausführlich, wie Sie mit Ihrem Problem umgehen können und was Sie tun können, wenn Sie mehr erfahren möchten. Der Einfachheit halber möchten Sie Folgendes tun

double whateverYouWantToChange = whateverYouWantToChange.ToString("F2");

Wenn Sie dies für eine Währung wünschen, können Sie es einfacher machen, indem Sie "C2" anstelle von "F2" eingeben.

Jeff Jose
quelle
1
Double Amount = 0;
string amount;
amount=string.Format("{0:F2}", Decimal.Parse(Amount.ToString()));
JIYAUL MUSTAPHA
quelle
1

Wenn Sie nur 2 Dezimalstellen behalten müssen (dh alle restlichen Dezimalstellen abschneiden):

decimal val = 3.14789m;
decimal result = Math.Floor(val * 100) / 100; // result = 3.14

Wenn Sie nur 3 Dezimalstellen behalten müssen:

decimal val = 3.14789m;
decimal result = Math.Floor(val * 1000) / 1000; // result = 3.147
Aleksei Mialkin
quelle