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()?

Odpowiedzi:


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

lub

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

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


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).


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


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).


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");

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.


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
===================


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.


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

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"

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

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


+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,


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

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.