Come arrotondare un valore decimale a 2 decimali (per l'output su una pagina)


649

Quando si visualizza il valore di un decimale attualmente con .ToString(), è preciso come 15 decimali e, poiché lo sto usando per rappresentare dollari e centesimi, voglio solo che l'output sia di 2 decimali.

Uso una variante di .ToString()per questo?

Risposte:


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

o

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

31
il problema qui è quando abbiamo 0,00; restituisce una stringa vuota.
Jronny,

164
Quindi è possibile eseguire decimalVar.ToString ("0. ##"). Puoi anche usare 0.00 come stringa di formattazione.
albertein

54
Con questa soluzione, non avrai la formattazione della cultura che ti aspetteresti quando leggi i numeri. Per questo dovresti usare ToString ("N2") o ToString ("N").
Shautieh,

2
Il metodo @Hill Decimale Doubletype ToStringaccetta l'argomento per la formattazione. Prova prima a convertire il tuo valore in Decimale / Doppio.
sohaiby,

1
@ f470071 I decimali sono tipi di valore e come tali non vengono mai "modificati". Indipendentemente da ciò, ToString () non ha mai dovuto modificare il contenuto di qualunque cosa venga chiamato.
Justin Skiles,

590

So che questa è una vecchia domanda, ma sono stato sorpreso di vedere che nessuno sembrava pubblicare una risposta;

  1. Non ho usato l'arrotondamento dei banchieri
  2. Non mantenere il valore come un decimale.

Questo è quello che vorrei usare:

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

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


3
ToString o string.Format non usa l'arrotondamento dei banchieri: msdn.microsoft.com/en-us/library/0c899ak8.aspx#sectionToggle1
Matthijs Wessels

1
@MatthijsWessels Lo so ... ma non mantiene neanche il valore come decimale.
Mike M.

1
Questo è un modo migliore per rappresentare veramente due cifre decimali in quanto non eliminerà gli zeri finali.
LiquidDrummer,

355
decimalVar.ToString("F");

Questo sarà:

  • Arrotondare al secondo decimale, ad es. 23.45623.46
  • Assicurarsi che ci siano sempre 2 cifre decimali, ad es. 2323.00; 12.512.50

Ideale per visualizzare la valuta.

Consulta la documentazione su ToString ("F") (grazie a Jon Schneider).


10
Funziona bene quando ha solo 1 decimale; .ToString ("#. ##") non riesce. Questa risposta è molto migliore
Eric Frick del

2
Non arrotonderebbe 23.456 => 23.46?
rtpHarry,

14
Documentazione sul significato della "F" qui e su come funziona: msdn.microsoft.com/en-us/library/…
Jon Schneider,

4
Perché no .ToString ("N") invece di "F"? Comprendo che funzioneranno entrambi per le esigenze di questa domanda, ma N inserirà anche virgole per i numeri in migliaia.
jgerman,

Nota: .potrebbe essere sostituito con in ,base alla cultura. Dovresti passare CultureInfo.InvariantCultureil secondo argomento per disabilitarlo.
Duncan Luk,


56

Dato decimale d = 12,345; le espressioni d.ToString ("C") o String.Format ("{0: C}", d) producono $ 12,35 - si noti che vengono utilizzate le impostazioni di valuta della cultura corrente, incluso il simbolo.

Si noti che "C" utilizza il numero di cifre della cultura corrente. Puoi sempre ignorare l'impostazione predefinita per forzare la precisione necessaria con i mi C{Precision specifier}piace String.Format("{0:C2}", 5.123d).


4
@ Slick86 - il segno
attuale

48

Se lo si desidera formattato con virgole e un punto decimale (ma nessun simbolo di valuta), come 3.456.789,12 ...

decimalVar.ToString("n2");

1
Risposta migliore poiché la domanda riguardava l'output in una pagina e la formattazione dei numeri è importante per i grandi numeri. Inoltre, "n *" tiene conto della cultura corrente, quindi potrebbe essere "3.456.789,12", "3 456 789,12", ecc.
Shautieh,

29

Esistono già due risposte con punteggio elevato che fanno riferimento a Decimal.Round (...) ma penso che sia necessaria una spiegazione in più - perché esiste un'importante proprietà inaspettata di Decimal che non è ovvia.

Un decimale "sa" quanti decimali ha basato sulla sua provenienza.

Ad esempio, potrebbe non essere previsto quanto segue:

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"

Fare le stesse operazioni con Doublenon darà decimali ( "25") per ciascuna delle precedenti.

Quando vuoi un decimale con 2 decimali c'è una probabilità del 95% circa perché è la valuta, nel qual caso probabilmente va bene per il 95% delle volte:

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

O in XAML basta usare {Binding Price, StringFormat=c}

Un caso in cui mi sono imbattuto in cui avevo bisogno di un decimale come un decimale è stato quando ho inviato XML al servizio web di Amazon. Il servizio si lamentava perché un valore decimale (originariamente da SQL Server) veniva inviato 25.1200e rifiutato ( 25.12era il formato previsto).

Tutto quello che dovevo fare era Decimal.Round(...)con 2 cifre decimali per risolvere il problema.

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

TypedValueè di tipo Decimalquindi non potevo semplicemente fare ToString("N2")e avevo bisogno di arrotondarlo e tenerlo come un decimal.


5
+1 questa è un'ottima risposta. Quando dici che System.Decimal "sa quante posizioni decimali ha" - il termine è che System.Decimal non si auto-normalizza come lo sono gli altri tipi in virgola mobile. Un'altra proprietà utile di System.Decimal è che il risultato delle operazioni matematiche ha sempre il numero più alto di posizioni decimali dagli argomenti di input, ad es. 1.0m + 2.000m = 3.000m . È possibile utilizzare questo fatto per forzare un decimale senza decimali a 2 decimali semplicemente moltiplicandolo per 1,00 m ad es. 10m * 1.00m = 10.00m .
MattDavey,

2
MattDavey non è corretto, viene aggiunta la precisione decimale. (1.0m * 1.00m) .ToString () = "1.000"
Kaido

2
È molto, molto utile sapere che "Un decimale 'sa' quante posizioni decimali ha basato sulla sua provenienza." Molte grazie!
iheartcsharp, l'

21

Ecco un piccolo programma Linqpad per mostrare diversi formati:

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

Ecco i risultati:

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

Molto raramente vorresti una stringa vuota se il valore è 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"

La risposta più votata è errata e ha perso 10 minuti di tempo (la maggior parte) delle persone.


1
fondamentalmente "#"significa cifra del numero (se necessario) (senza imbottitura, se non necessario) "0"significa cifra del numero (non mater cosa) (posti a zero se non disponibile)
Mr Heelis

10

La risposta di Mike M. è stata perfetta per me su .NET, ma .NET Core non ha un decimal.Roundmetodo al momento della stesura.

In .NET Core, ho dovuto usare:

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

Un metodo hacky, inclusa la conversione in stringa, è:

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

Nessuno di questi ha fatto esattamente ciò di cui avevo bisogno, per forzare 2 dp e arrotondare come0.005 -> 0.01

Forzare 2 dp richiede di aumentare la precisione di 2 dp per garantire che abbiamo almeno 2 dp

quindi arrotondare per assicurarsi che non abbiamo più di 2 dp

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

6.665m.ToString() -> "6.67"

6.6m.ToString() -> "6.60"

9

La risposta più votata descrive un metodo per formattare la rappresentazione in stringa del valore decimale e funziona.

Tuttavia, se si desidera effettivamente modificare la precisione salvata sul valore effettivo, è necessario scrivere qualcosa di simile al seguente:

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

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

7

È possibile utilizzare system.globalization per formattare un numero in qualsiasi formato richiesto.

Per esempio:

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

Se hai un decimal d = 1.2300000e devi tagliarlo con 2 cifre decimali, puoi stamparlo in questo modo d.Tostring("F2",ci);dove F2 sta formando una stringa con 2 cifre decimali e ci è la localizzazione o cultureinfo.

per maggiori informazioni controlla questo link
http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx


+1 ma - l'oggetto CultureInfo influirebbe solo sul carattere unicode utilizzato per indicare la posizione decimale. per esempio. fr-FR userebbe una virgola anziché un punto. Non è correlato al numero di cifre decimali visualizzate.
MattDavey,

4

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

Questo link spiega in dettaglio come è possibile gestire il problema e cosa è possibile fare se si desidera ulteriori informazioni. Per motivi di semplicità, quello che vuoi fare è

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

se lo desideri per una valuta, puoi semplificarlo digitando "C2" anziché "F2"


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

1

Se è necessario mantenere solo 2 cifre decimali (ovvero tagliare tutte le cifre decimali):

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

Se è necessario mantenere solo 3 cifre decimali:

decimal val = 3.14789m;
decimal result = Math.Floor(val * 1000) / 1000; // result = 3.147
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.