Lors de l'affichage de la valeur d'une décimale actuellement avec .ToString()
, il est précis de 15 décimales, et comme je l'utilise pour représenter des dollars et des cents, je ne souhaite que la sortie soit à 2 décimales.
Est-ce que j'utilise une variante de .ToString()
pour cela?
decimalVar.ToString ("#.##"); // returns "" when decimalVar == 0
ou
decimalVar.ToString ("0.##"); // returns "0" when decimalVar == 0
Je sais que c’est une vieille question, mais j’ai été surpris de constater que personne ne semblait répondre à cette question;
C'est ce que j'utiliserais:
decimal.Round(yourValue, 2, MidpointRounding.AwayFromZero);
decimalVar.ToString("F");
Cette volonté:
Idéal pour la monnaie et l'affichage des montants monétaires.
Pour la documentation sur ToString ("F"): http://msdn.Microsoft.com/en-us/library/dwhawy9k%28v=vs.110%29.aspx#FFormatString (avec le remerciement de Jon Schneider)
Si vous avez juste besoin de cela pour l'affichage, utilisez string.Format
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:
Étant donné décimal d = 12.345; les expressions d.ToString ("C") ou String.Format ("{0: C}", d) donne 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}
comme String.Format("{0:C2}", 5.123d)
.
Si vous souhaitez le mettre en forme avec des virgules et un point décimal (mais pas de symbole monétaire), tel que 3 356 789,12 ...
decimalVar.ToString("n2");
Il existe déjà deux réponses très cotées qui font référence à Decimal.Round (...), mais je pense qu'un peu plus d'explication est nécessaire - car il existe une propriété importante et inattendue de Decimal qui n'est pas évidente.
Une virgule "sait" combien de décimales elle a été créée 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"
Effectuer les mêmes opérations avec Double
ne 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 chances que ce soit parce que c'est la devise, auquel cas c'est probablement bien pour 95% du temps:
Decimal.Parse("25.0").ToString("c") => "$25.00"
Ou, en XAML, vous utilisez simplement {Binding Price, StringFormat=c}
Un cas que j'ai rencontré où j'avais besoin d'une décimale comme décimale était lors de l'envoi de XML au service Web d'Amazon. Le service se plaignait car une valeur décimale (à l'origine de SQL Server) était envoyée sous le nom 25.1200
et 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"
}
TypedValue
est de type Decimal
et je ne pouvais donc pas simplement faire ToString("N2")
, je devais l'arrondir et le conserver en tant que decimal
.
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
===================
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 de temps (de la plupart des) personnes.
Aucun de ceux-ci n'a fait exactement ce dont j'avais besoin, pour forcer 2 d.p. et arrondi par 0.005 -> 0.01
Forcer 2 p.p. nécessite d’augmenter la précision de 2 d.p. pour s'assurer que nous avons au moins 2 dp.
puis nous arrondissons pour nous assurer que nous n’avons pas plus de 2d.p.
Math.Round(exactResult * 1.00m, 2, MidpointRounding.AwayFromZero)
6.665m.ToString() -> "6.67"
6.6m.ToString() -> "6.60"
La réponse la mieux notée décrit une méthode pour formater la représentation sous forme de chaîne de la valeur décimale, et cela fonctionne.
Toutefois, si vous souhaitez réellement modifier la précision enregistrée en valeur réelle, vous devez écrire quelque chose comme ce qui suit:
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"));
}
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 avez un decimal d = 1.2300000
et que vous devez le réduire à 2 décimales, il peut être imprimé comme ceci d.Tostring("F2",ci);
où F2 est une chaîne de caractères formatant à 2 décimales et ci est le paramètre régional ou cultureinfo.
pour plus d'informations, consultez ce lien
http://msdn.Microsoft.com/en-us/library/dwhawy9k.aspx
La réponse de Mike M. était parfait pour moi sur .NET, mais .NET Core n'a pas de méthode decimal.Round
au moment de la rédaction.
Dans .NET Core, je devais utiliser:
decimal roundedValue = Math.Round(rawNumber, 2, MidpointRounding.AwayFromZero);
Une méthode de 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);
}
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 voulez en savoir plus. Pour des raisons de simplicité, ce que vous voulez faire est
double whateverYouWantToChange = whateverYouWantToChange.ToString("F2");
si vous voulez ceci pour une devise, vous pouvez le simplifier en tapant "C2" au lieu de "F2"
Double Amount = 0;
string amount;
amount=string.Format("{0:F2}", Decimal.Parse(Amount.ToString()));