Jak zaokrąglić wartość dziesiętną do 2 miejsc po przecinku (do wydruku na stronie)

648

Wyświetlając obecnie wartość dziesiętną .ToString(), dokładność wynosi 15 miejsc po przecinku, a ponieważ używam jej do reprezentowania dolarów i centów, chcę, aby wynik był tylko 2 miejsca po przecinku.

Czy używam do tego odmiany .ToString()?

wow
źródło

Odpowiedzi:

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

lub

decimalVar.ToString ("0.##"); // returns "0"  when decimalVar == 0
albertein
źródło
31
problemem jest to, że mamy 0,00; zwraca pusty ciąg.
Jronny
164
Następnie możesz wykonać decimalVar.ToString („0. ##”). Możesz także użyć 0,00 jako ciągu formatującego.
albertein
54
Dzięki temu rozwiązaniu nie będziesz mieć formatowania kultury, którego można by oczekiwać podczas czytania liczb. W tym celu należy użyć ToString („N2”) lub ToString („N”).
Shautieh
2
Metoda @Hill Decimali Doubletype ToStringprzyjmuje argument do formatowania. Najpierw spróbuj przekonwertować swoją wartość na dziesiętną / podwójną.
sohaiby,
1
@ f470071 Dziesiętne są typami wartości i jako takie nigdy nie są „modyfikowane”. Niezależnie od tego nigdy nie oczekiwano, że ToString () zmodyfikuje zawartość tego, co jest wywoływane.
Justin Skiles
589

Wiem, że to stare pytanie, ale zdziwiłem się, widząc, że nikt nie wydaje odpowiedzi na to pytanie;

  1. Nie używano zaokrąglania przez bankierów
  2. Nie zachował wartości dziesiętnej.

Chciałbym użyć tego:

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

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

Mike M.
źródło
3
ToString lub string.Format nie używaj zaokrąglania banków: msdn.microsoft.com/en-us/library/0c899ak8.aspx#sectionToggle1
Matthijs Wessels
1
@MatthijsWessels Wiem ... ale nie zachowuje też wartości dziesiętnej.
Mike M.
1
Jest to lepszy sposób na prawdziwe odwzorowanie dwóch miejsc po przecinku, ponieważ nie będzie on usuwał końcowych zer.
LiquidDrummer
354
decimalVar.ToString("F");

Spowoduje to:

  • Zaokrąglić do 2 miejsc po przecinku, np. 23.45623.46
  • Upewnij się, że zawsze są 2 miejsca po przecinku, np. 2323.00; 12.512.50

Idealny do wyświetlania waluty.

Sprawdź dokumentację ToString („F”) (podziękowania dla Jona Schneidera).

Sofox
źródło
10
Działa to dobrze, gdy ma tylko 1 miejsce po przecinku; Błąd .ToString („#. ##”). Ta odpowiedź jest znacznie lepsza
Eric Frick
2
Czy nie zaokrągliby 23,456 => 23,46?
rtpHarry
14
Dokumentacja na temat tego, co oznacza „F” i jak to działa: msdn.microsoft.com/en-us/library/…
Jon Schneider
4
Dlaczego nie .ToString („N”) zamiast „F”? Rozumiem, że oba będą działać na potrzeby tego pytania, ale N umieści także przecinki dla liczb w tysiącach.
jgerman
Uwaga: .można je zastąpić ,na podstawie kultury. Powinieneś przekazać CultureInfo.InvariantCulturejako drugi argument, aby to wyłączyć.
Duncan Luk
106

Jeśli potrzebujesz tego tylko do wyświetlania, użyj string.Format

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

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

„M” jest przyrostkiem dziesiętnym. Informacje o sufiksie dziesiętnym:

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

Jorge Ferreira
źródło
10
Technicznie rzecz biorąc, po przecinku byłoby to 123,4567 m, tak? Bez przyrostka „m” jest podwójny
Adam Tegen
2
lub skrót $ „{wartość: 0,00}”
mamczas
56

Biorąc pod uwagę dziesiętne d = 12,345; wyrażenia d.ToString („C”) lub String.Format („{0: C}”, d) dają 12,35 USD - zwróć uwagę, że używane są ustawienia waluty bieżącej kultury, w tym symbol.

Zauważ, że „C” używa liczby cyfr z bieżącej kultury. Zawsze można przesłonić domyślne wymusić niezbędną precyzję z C{Precision specifier}niczym String.Format("{0:C2}", 5.123d).

Hafthor
źródło
4
@ Slick86 - aktualny znak
fubo
48

Jeśli chcesz go sformatować przecinkami, a także kropką dziesiętną (ale bez symbolu waluty), na przykład 3 456 789,12 ...

decimalVar.ToString("n2");
Joel Mueller
źródło
1
Lepsza odpowiedź, ponieważ pytanie dotyczyło wydruku na stronie, a formatowanie liczb jest ważne w przypadku dużych liczb. Również „n *” bierze pod uwagę obecną kulturę, więc może to być „3.456.789,12”, „3 456 789,12” itp.
Shautieh
29

Istnieją już dwie wysoko punktowane odpowiedzi, które odnoszą się do Decimal.Round (...), ale myślę, że potrzebne jest trochę więcej wyjaśnień - ponieważ istnieje nieoczekiwana ważna właściwość Decimal, która nie jest oczywista.

Po przecinku „wie”, ile miejsc po przecinku ma na podstawie tego, skąd pochodzi.

Na przykład mogą być nieoczekiwane:

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"

Wykonanie tych samych operacji z Doublenie da miejsc dziesiętnych ( "25") dla każdego z powyższych.

Jeśli chcesz od miejsc po przecinku do 2 miejsc po przecinku, masz około 95% szansy, ponieważ jest to waluta, w którym to przypadku jest to prawdopodobnie w porządku przez 95% czasu:

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

Lub w XAML, którego właśnie używasz {Binding Price, StringFormat=c}

Jeden przypadek, w którym natrafiłem na miejsce dziesiętne jako dziesiętne, dotyczył wysyłania XML do serwisu Amazon. Usługa narzekała, ponieważ wartość dziesiętna (pierwotnie z SQL Server) była wysyłana jako 25.1200odrzucana ( 25.12oczekiwany format).

Wszystko, co musiałem zrobić, to Decimal.Round(...)2 miejsca po przecinku, aby rozwiązać problem.

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

TypedValuejest typu, Decimalwięc nie mogłem tego zrobić ToString("N2")i musiałem go zaokrąglić i zachować jako decimal.

Simon_Weaver
źródło
5
+1 to świetna odpowiedź. Kiedy mówisz, że System.Decimal „wie, ile jest miejsc dziesiętnych” - oznacza to, że System.Decimal nie jest samonormalizujący, podobnie jak inne typy zmiennoprzecinkowe. Inną przydatną właściwością System.Decimal jest to, że wynik operacji matematycznych zawsze ma największą liczbę miejsc dziesiętnych spośród argumentów wejściowych, tj. 1,0 m + 2,000 m = 3,000 m . Możesz użyć tego faktu, aby wymusić liczbę dziesiętną bez miejsc dziesiętnych do 2 miejsc po przecinku, po prostu mnożąc ją przez 1,00 m np. 10 m * 1,00 m = 10,00 m .
MattDavey,
2
MattDavey's jest niepoprawny, dodawana jest dokładność dziesiętna. (1,0m * 1,00m) .ToString () = "1.000"
Kaido,
2
Bardzo, bardzo przydatne jest wiedzieć, że „Dziesiętny” wie „ile miejsc dziesiętnych ma na podstawie tego, skąd pochodzi”. Wielkie dzięki!
iheartcsharp
21

Oto mały program Linqpad do wyświetlania różnych formatów:

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("===================");
}

Oto wyniki:

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
===================
Co by było fajne
źródło
16

Metoda Math.Round (dziesiętna, Int32)

John Smith
źródło
czy to nie używa zaokrąglania przez bankiera?
Danimal
Jest to najlepszy sposób, ponieważ wartość nie jest konwertowana na ciąg i nadal można wykonywać operacje matematyczne
shinji14
@Danimal: Możesz podać trzeci argument, aby zmienić typ zaokrąglania
Jay Sullivan
11

Bardzo rzadko chciałbyś mieć pusty ciąg, jeśli wartość wynosi 0.

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"

Najwyżej oceniana odpowiedź jest niepoprawna i zmarnowała 10 minut czasu (większości) ludzi.

Goamn
źródło
1
w zasadzie "#"oznacza cyfrę numeru (w razie potrzeby) (bez dopełnienia, jeśli nie jest potrzebna) "0"oznacza cyfrę numeru (bez względu na to, co) (wypełnione zerami, jeśli nie są dostępne)
Pan Heelis
10

Odpowiedź Mike M. była idealna dla mnie na .NET, ale .NET Core nie ma decimal.Roundmetody w chwili pisania.

W .NET Core musiałem użyć:

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

Metoda hacky, w tym konwersja na ciąg znaków, to:

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

    return string.Format("{0:0.00}", myNumber);
}
Hokej
źródło
9

Żadne z nich nie zrobiło dokładnie tego, czego potrzebowałem, aby wymusić 2 dp i zaokrąglić w górę jako0.005 -> 0.01

Wymuszenie 2 dp wymaga zwiększenia precyzji o 2 dp, aby upewnić się, że mamy co najmniej 2 dp

następnie zaokrąglanie, aby upewnić się, że nie mamy więcej niż 2 dp

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

6.665m.ToString() -> "6.67"

6.6m.ToString() -> "6.60"
Kaido
źródło
9

Najwyżej oceniana odpowiedź opisuje metodę formatowania reprezentacji ciągu wartości dziesiętnej i działa.

Jeśli jednak chcesz zmienić zapisaną dokładność na rzeczywistą wartość, musisz napisać coś takiego:

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;
    }
}

Przykładowy test jednostkowy:

[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
źródło
7

Możesz użyć system.globalization, aby sformatować liczbę w dowolnym wymaganym formacie.

Na przykład:

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

Jeśli masz a decimal d = 1.2300000i musisz przyciąć go do 2 miejsc po przecinku, możesz go wydrukować w ten sposób, d.Tostring("F2",ci);gdzie F2 jest łańcuchem tworzącym do 2 miejsc po przecinku, a ci jest ustawieniem narodowym lub kulturą.

Aby uzyskać więcej informacji, sprawdź ten link
http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx

Smitha Poluri
źródło
+1, ale - obiekt CultureInfo wpływałby tylko na znak Unicode używany do oznaczenia miejsca dziesiętnego. na przykład. fr-FR użyłby przecinka zamiast kropki. Nie jest to związane z liczbą renderowanych miejsc dziesiętnych.
MattDavey,
4

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

Ten link szczegółowo wyjaśnia, jak poradzić sobie z problemem i co możesz zrobić, jeśli chcesz dowiedzieć się więcej. Dla uproszczenia chcesz to zrobić

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

jeśli chcesz tego dla waluty, możesz to ułatwić, wpisując „C2” zamiast „F2”

Jeff Jose
źródło
1
Double Amount = 0;
string amount;
amount=string.Format("{0:F2}", Decimal.Parse(Amount.ToString()));
JIYAUL MUSTAPHA
źródło
1

Jeśli chcesz zachować tylko 2 miejsca po przecinku (tj. Odetnij wszystkie pozostałe cyfry po przecinku):

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

Jeśli chcesz zachować tylko 3 miejsca po przecinku:

decimal val = 3.14789m;
decimal result = Math.Floor(val * 1000) / 1000; // result = 3.147
Aleksei Mialkin
źródło