Comment arrondir une valeur décimale à 2 décimales (pour la sortie sur une page)

649

Lors de l'affichage de la valeur d'une décimale actuellement avec .ToString(), il est précis d'aimer 15 décimales, et puisque je l'utilise pour représenter des dollars et des cents, je veux seulement que la sortie soit à 2 décimales.

Dois-je utiliser une variante de .ToString()pour cela?

wow
la source

Réponses:

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

ou

decimalVar.ToString ("0.##"); // returns "0"  when decimalVar == 0
albertein
la source
31
le problème ici est quand nous avons 0,00; il renvoie une chaîne vide.
Jronny
164
Ensuite, vous pouvez faire decimalVar.ToString ("0. ##"). Vous pouvez également utiliser 0,00 comme chaîne de formatage.
albertein
54
Avec cette solution, vous n'aurez pas la mise en forme de la culture que vous attendez lors de la lecture des nombres. Pour cela, vous devez utiliser ToString ("N2") ou ToString ("N").
Shautieh
2
La méthode @Hill Decimalet Doubletype ToStringaccepte l'argument pour le formatage. Essayez de convertir d'abord votre valeur en décimal / double.
sohaiby
1
@ f470071 Les décimales sont des types de valeur et en tant que telles ne sont jamais "modifiées". Quoi qu'il en soit, ToString () n'a jamais été censé modifier le contenu de ce qu'il est appelé.
Justin Skiles
590

Je sais que c'est une vieille question, mais j'ai été surpris de voir que personne ne semblait poster une réponse à cela;

  1. N'a pas utilisé d'arrondis de banquiers
  2. N'a pas conservé la valeur sous forme décimale.

Voici ce que j'utiliserais:

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

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

Mike M.
la source
3
ToString ou string.Format n'utilisez pas d'arrondi bancaire: msdn.microsoft.com/en-us/library/0c899ak8.aspx#sectionToggle1
Matthijs Wessels
1
@MatthijsWessels Je sais ... mais il ne garde pas non plus la valeur sous forme décimale.
Mike M.
1
C'est une meilleure façon de représenter véritablement deux décimales car elle ne supprimera pas les zéros de fin.
LiquidDrummer
355
decimalVar.ToString("F");

Cette volonté:

  • Arrondissez à 2 décimales, par exemple. 23.45623.46
  • Assurez-vous qu'il y a toujours 2 décimales, par exemple. 2323.00; 12.512.50

Idéal pour afficher des devises.

Consultez la documentation sur ToString ("F") (merci à Jon Schneider).

Sofox
la source
10
Cela fonctionne bien quand il n'a qu'une décimale; .ToString ("#. ##") échoue. Cette réponse est bien meilleure
Eric Frick
2
Ne tournerait-il pas 23.456 => 23.46?
rtpHarry
14
Documentation sur ce que le "F" signifie ici et comment il fonctionne: msdn.microsoft.com/en-us/library/…
Jon Schneider
4
Pourquoi pas .ToString ("N") au lieu de "F"? Je crois comprendre qu'ils fonctionneront tous les deux pour les besoins de cette question, mais N mettra également des virgules pour les nombres par milliers.
jgerman
Remarque: le .peut être remplacé par ,basé sur la culture. Vous devez passer CultureInfo.InvariantCulturecomme deuxième argument pour le désactiver.
Duncan Luk
106

Si vous en avez juste besoin pour l'affichage, utilisez string.

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

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

Le "m" est un suffixe décimal. À propos du suffixe décimal:

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

Jorge Ferreira
la source
10
Techniquement, pour une décimale, ce serait 123,4567m, oui? Sans le suffixe "m", c'est un double
Adam Tegen
2
ou raccourci $ "{valeur: 0,00}"
mamczas
56

Étant donné d décimal = 12,345; les expressions d.ToString ("C") ou String.Format ("{0: C}", d) rapportent 12,35 $ - notez que les paramètres de devise de la culture actuelle, y compris le symbole, sont utilisés.

Notez que "C" utilise le nombre de chiffres de la culture actuelle. Vous pouvez toujours remplacer la valeur par défaut pour forcer la précision nécessaire avec C{Precision specifier}like String.Format("{0:C2}", 5.123d).

Hafthor
la source
4
@ Slick86 - le signe actuel
fubo
48

Si vous voulez le mettre en forme avec des virgules ainsi qu'un point décimal (mais pas de symbole monétaire), comme 3,456,789.12 ...

decimalVar.ToString("n2");
Joel Mueller
la source
1
Meilleure réponse car la question portait sur la sortie sur une page, et la mise en forme des nombres est importante pour les grands nombres. En outre, "n *" prend en compte la culture actuelle, il peut donc s'agir de "3.456.789,12", "3 456 789,12", etc.
Shautieh
29

Il y a déjà deux réponses à haut score qui se réfèrent à Decimal.Round (...) mais je pense qu'un peu plus d'explications sont nécessaires - car il y a une propriété importante inattendue de Decimal qui n'est pas évidente.

Une décimale «sait» combien de décimales elle a en fonction de son origine.

Par exemple, les éléments suivants peuvent être inattendus:

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"

Faire les mêmes opérations avec Doublene donnera aucune décimale ( "25") pour chacun des éléments ci-dessus.

Lorsque vous voulez une décimale à 2 décimales, il y a environ 95% de chance, c'est parce que c'est de la monnaie, auquel cas cela est probablement correct pour 95% du temps:

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

Ou en XAML, vous utilisez simplement {Binding Price, StringFormat=c}

J'ai rencontré un cas où j'avais besoin d'une décimale AS comme décimale lors de l'envoi de XML au service Web d'Amazon. Le service se plaignait car une valeur décimale (originaire de SQL Server) était envoyée 25.1200et rejetée ( 25.12était le format attendu).

Tout ce que je devais faire était Decimal.Round(...)avec 2 décimales pour résoudre le problème.

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

TypedValueest de type Decimaldonc je ne pouvais pas simplement faire ToString("N2")et je devais l'arrondir et le garder comme decimal.

Simon_Weaver
la source
5
+1 c'est une excellente réponse. Lorsque vous dites que System.Decimal "sait combien de décimales il y a" - le terme est que System.Decimal ne s'auto-normalise pas comme les autres types à virgule flottante. Une autre propriété utile de System.Decimal est que le résultat des opérations mathématiques a toujours le plus grand nombre de décimales des arguments d'entrée, c'est-à-dire. 1,0 m + 2 000 m = 3 000 m . Vous pouvez utiliser ce fait pour forcer une décimale sans décimales à 2 décimales simplement en la multipliant par 1,00 m, par exemple. 10 m * 1,00 m = 10,00 m .
MattDavey
2
MattDavey est incorrect, la précision décimale est ajoutée. (1.0m * 1.00m) .ToString () = "1.000"
Kaido
2
Il est très, très utile de savoir que "une décimale" sait "combien de décimales elle a en fonction de son origine." Merci beaucoup!
iheartcsharp
21

Voici un petit programme Linqpad pour montrer différents formats:

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

Voici les résultats:

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
===================
Ce qui serait cool
la source
16

Méthode Math.Round (Decimal, Int32)

John Smith
la source
cela n'utilise-t-il pas l'arrondi bancaire?
Danimal
C'est le meilleur moyen, car la valeur ne se convertit pas en chaîne et vous pouvez toujours effectuer des opérations mathématiques
shinji14
@Danimal: Vous pouvez fournir un troisième argument pour changer le type d'arrondi
Jay Sullivan
11

Très rarement, voudriez-vous une chaîne vide si la valeur est 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 réponse la mieux notée est incorrecte et a perdu 10 minutes (la plupart) du temps des gens.

goamn
la source
1
"#"signifie essentiellement le chiffre du nombre (si nécessaire) (sans rembourrage s'il n'est pas nécessaire) "0"signifie le chiffre du numéro (sans importance quoi) (rembourré avec des zéros si non disponible)
M. Heelis
10

La réponse de Mike M. était parfaite pour moi sur .NET, mais .NET Core n'a pas de decimal.Roundméthode au moment de la rédaction.

Dans .NET Core, j'ai dû utiliser:

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

Une méthode hacky, y compris la conversion en chaîne, est la suivante:

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
la source
9

Aucun de ceux-ci n'a fait exactement ce dont j'avais besoin, pour forcer 2 dp et arrondir comme0.005 -> 0.01

Forcer 2 dp nécessite d'augmenter la précision de 2 dp pour être sûr d'avoir au moins 2 dp

puis arrondi pour s'assurer que nous n'avons pas plus de 2 dp

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

6.665m.ToString() -> "6.67"

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

La réponse la mieux notée décrit une méthode de mise en forme de la représentation sous forme de chaîne de la valeur décimale, et cela fonctionne.

Cependant, si vous voulez réellement changer la précision enregistrée à la valeur réelle, vous devez écrire quelque chose comme ceci:

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 exemple de test unitaire:

[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
la source
7

Vous pouvez utiliser system.globalization pour formater un nombre dans n'importe quel format requis.

Par exemple:

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

Si vous en avez un decimal d = 1.2300000et que vous devez le couper à 2 décimales, il peut être imprimé comme ceci d.Tostring("F2",ci);où F2 est un formatage de chaîne à 2 décimales et ci est la locale ou cultureinfo.

pour plus d'informations, consultez ce lien
http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx

Smitha Poluri
la source
+1 mais - l'objet CultureInfo n'affecterait que le caractère unicode utilisé pour désigner la décimale. par exemple. fr-FR utiliserait une virgule au lieu d'un point. Ce n'est pas lié au nombre de décimales rendues.
MattDavey
4

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

Ce lien explique en détail comment vous pouvez gérer votre problème et ce que vous pouvez faire si vous souhaitez en savoir plus. Pour des raisons de simplicité, ce que vous voulez faire est

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

si vous le souhaitez pour une devise, vous pouvez le rendre plus facile en tapant "C2" au lieu de "F2"

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

Si vous devez conserver seulement 2 décimales (c'est-à-dire couper tous les autres chiffres décimaux):

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

Si vous ne devez conserver que 3 décimales:

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