Como posso arredondar um valor decimal para 2 casas decimais (para a saída em uma página)
Pergunta
Ao exibir o valor de uma decimal atualmente com .ToString()
, é preciso como 15 casas decimais, e desde que eu estou usando-o para representar dólares e centavos, eu só quero que a saída seja 2 casas decimais.
Eu uso uma variação de .ToString()
para isso?
Solução
decimalVar.ToString ("#.##"); // returns "" when decimalVar == 0
ou
decimalVar.ToString ("0.##"); // returns "0" when decimalVar == 0
Outras dicas
Eu sei que isto é uma questão antiga, mas fiquei surpreso ao ver que ninguém parecia para deixar uma resposta que;
- Não utilizar banqueiros arredondamento
- Não mantenha o valor como um decimal.
Isto é o que eu usaria:
decimal.Round(yourValue, 2, MidpointRounding.AwayFromZero);
decimalVar.ToString("F");
Esta vontade:
- arredondar para 2 casas decimais, por exemplo. 23,456 => 23.46
- Certifique-se de que não são sempre 2 casas decimais, por exemplo. 23 => 23,00, 12,5 => 12.50
Ideal para moeda e exibição de valores monetários.
Para documentação sobre ToString ( "F"): http://msdn.microsoft.com/en-us/library/dwhawy9k%28v=vs.110%29.aspx#FFormatString (com agradecimentos a Jon Schneider)
Se você só precisa deste para uso de exibição string.Format
String.Format("{0:0.00}", 123.4567m); // "123.46"
http://www.csharp-examples.net/string-format-double /
O "m" é um sufixo decimal. Sobre o sufixo decimal:
Dado
Note que "C" usos número de dígitos da cultura atual. Você sempre pode substituir padrão para forçar precisão necessária com C{Precision specifier}
como String.Format("{0:C2}", 5.123d)
.
Se você deseja que ele formatado com vírgulas, bem como um ponto decimal (mas nenhum símbolo de moeda), tais como 3,456,789.12 ...
decimalVar.ToString("n2");
Há já dois altos respostas de pontuação que se referem a Decimal.Round (...) mas eu acho que um pouco mais explicação é necessária -. Porque há uma importante propriedade inesperada de Decimal que não é óbvio
A decimal 'sabe' quantas casas decimais baseou em cima de onde ele veio.
Por exemplo, o seguinte pode ser inesperado:
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"
Fazendo as mesmas operações com Double
dará sem casas decimais ("25"
) para cada um dos acima.
Quando você quer um decimal para 2 casas decimais Há cerca de uma chance de 95% é porque moeda caso em que esta é provavelmente bom para 95% do tempo:
Decimal.Parse("25.0").ToString("c") => "$25.00"
Ou em XAML você acabou de usar {Binding Price, StringFormat=c}
Um caso eu corri para onde eu precisava de um decimal como um decimal foi ao enviar XML para webservice da Amazon. O serviço estava reclamando porque um valor decimal (originalmente do SQL Server) estava sendo enviado como 25.1200
e rejeitado, (25.12
foi o formato esperado).
Tudo que eu precisava fazer era Decimal.Round(...)
com 2 casas decimais para corrigir o problema.
// This is an XML message - with generated code by XSD.exe
StandardPrice = new OverrideCurrencyAmount()
{
TypedValue = Decimal.Round(product.StandardPrice, 2),
currency = "USD"
}
TypedValue
é do tipo Decimal
então eu não podia simplesmente fazer ToString("N2")
e necessária para arredondar-lo e mantê-lo como um decimal
.
Aqui está um pequeno programa LINQPad para mostrar diferentes formatos:
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("===================");
}
Aqui estão os resultados:
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
===================
Nenhum deles fez exatamente o que eu precisava, para forçar 2 D.P.. e até rodada como 0.005 -> 0.01
Forçar 2 D.P. requer o aumento da precisão por 2 D.P. para garantir que temos pelo menos 2 D.P.
, em seguida, o arredondamento para garantir que não têm mais de 2 D.P..
Math.Round(exactResult * 1.00m, 2, MidpointRounding.AwayFromZero)
6.665m.ToString() -> "6.67"
6.6m.ToString() -> "6.60"
Muito raramente que você quer um texto vazio se o valor for 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"
A resposta mais votados é incorreto e desperdiçou 10 minutos de (mais) tempo das pessoas.
A resposta mais votadas descreve um método para formatar o representação string do valor decimal, e ele funciona.
No entanto, se você realmente deseja alterar a precisão salvo com o valor real, você precisa escrever algo como o seguinte:
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;
}
}
Um exemplo de teste unidade:
[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"));
}
Você pode usar System.Globalization para formatar um número em qualquer formato exigido.
Por exemplo:
system.globalization.cultureinfo ci = new system.globalization.cultureinfo("en-ca");
Se você tem um decimal d = 1.2300000
e você precisa prepará-la para 2 casas decimais, então ele pode ser impressas como esta d.Tostring("F2",ci);
onde F2 é formatação corda para 2 casas decimais e ci é o local ou o CultureInfo.
para mais informações consultar este link
http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx
Mike M. foi perfeito para mim em .NET, mas .NET Core não tem um método decimal.Round
no momento da escrita.
Em .NET Core, eu tive que usar:
decimal roundedValue = Math.Round(rawNumber, 2, MidpointRounding.AwayFromZero);
Um método hacky, incluindo a conversão para string, é:
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
Este link explica em detalhes como você pode lidar com o seu problema e que você pode fazer se você quiser aprender mais. Para fins de simplicidade, o que você quer fazer é
double whateverYouWantToChange = whateverYouWantToChange.ToString("F2");
Se você quer isso para uma moeda, você pode torná-lo mais fácil de digitar "C2" em vez de "F2"