¿Cómo redondeo un valor decimal a 2 decimales (para salida en una página)


649

Cuando se muestra el valor de un decimal actualmente con .ToString(), es preciso que le gusten 15 lugares decimales, y como lo estoy usando para representar dólares y centavos, solo quiero que la salida sea 2 lugares decimales.

¿Utilizo una variación de .ToString()para esto?

Respuestas:


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

o

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

31
El problema aquí es cuando tenemos 0.00; devuelve una cadena vacía.
Jronny

164
Entonces podría hacer decimalVar.ToString ("0. ##"). También puede usar 0.00 como la cadena de formato.
albertein

54
Con esta solución, no tendrá el formato de cultura que uno esperaría al leer números. Para esto, debe usar ToString ("N2") o ToString ("N").
Shautieh

2
El método @Hill Decimaland Doubletype ToStringacepta argumentos para formatear. Intente convertir su valor a decimal / doble primero.
sohaiby

1
@ f470071 Los decimales son tipos de valor y, como tales, nunca se "modifican". En cualquier caso, nunca se ha esperado que ToString () modifique el contenido de lo que se llame.
Justin Skiles

590

Sé que esta es una vieja pregunta, pero me sorprendió ver que nadie parecía publicar una respuesta que;

  1. No utilicé banqueros redondeando
  2. No mantuvo el valor como un decimal.

Esto es lo que usaría:

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

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


3
ToString o string.Format no utiliza redondeo de banqueros: msdn.microsoft.com/en-us/library/0c899ak8.aspx#sectionToggle1
Matthijs Wessels

1
@MatthijsWessels Lo sé ... pero tampoco mantiene el valor como decimal.
Mike M.

1
Esta es una mejor manera de representar realmente dos lugares decimales, ya que no eliminará ceros finales.
LiquidDrummer

355
decimalVar.ToString("F");

Esta voluntad:

  • Redondear a 2 decimales, por ejemplo. 23.45623.46
  • Asegúrese de que siempre haya 2 decimales, por ejemplo. 2323.00; 12.512.50

Ideal para mostrar moneda.

Consulte la documentación en ToString ("F") (gracias a Jon Schneider).


10
Esto funciona bien cuando solo tiene 1 decimal; .ToString ("#. ##") falla. Esta respuesta es mucho mejor
Eric Frick

2
¿No redondearía 23.456 => 23.46?
rtpHarry

14
Documentación sobre lo que significa "F" aquí y cómo funciona: msdn.microsoft.com/en-us/library/…
Jon Schneider

44
¿Por qué no .ToString ("N") en lugar de "F"? Tengo entendido que ambos trabajarán para las necesidades de esta pregunta, pero N también colocará comas por miles.
jgerman

Nota: El .puede ser reemplazado por ,basado en la cultura. Debe pasar CultureInfo.InvariantCulturecomo el segundo argumento para deshabilitar esto.
Duncan Luk


56

Dado decimal d = 12.345; las expresiones d.ToString ("C") o String.Format ("{0: C}", d) rinden $ 12.35 ; tenga en cuenta que se utiliza la configuración de moneda de la cultura actual, incluido el símbolo.

Tenga en cuenta que "C" utiliza el número de dígitos de la cultura actual. Siempre puede anular el valor predeterminado para forzar la precisión necesaria con me C{Precision specifier}gusta String.Format("{0:C2}", 5.123d).


44
@ Slick86 - el signo actual
fubo

48

Si lo desea formateado con comas, así como un punto decimal (pero sin símbolo de moneda), como 3,456,789.12 ...

decimalVar.ToString("n2");

1
Mejor respuesta ya que la pregunta era sobre la salida en una página, y el formato de números es importante para los números grandes. Además, "n *" tiene en cuenta la cultura actual, por lo que podría ser "3.456.789,12", "3 456 789,12", etc.
Shautieh

29

Ya hay dos respuestas de alta puntuación que se refieren a Decimal. Redonda (...) pero creo que se necesita un poco más de explicación, porque hay una propiedad inesperada e importante de Decimal que no es obvia.

Un decimal 'sabe' cuántos decimales tiene en función de su origen.

Por ejemplo, lo siguiente puede 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"

Hacer las mismas operaciones con Doubleno dará lugares decimales ( "25") para cada uno de los anteriores.

Cuando quieres un decimal a 2 decimales, hay aproximadamente un 95% de posibilidades de que sea porque es moneda, en cuyo caso esto probablemente esté bien el 95% del tiempo:

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

O en XAML solo usas {Binding Price, StringFormat=c}

Un caso con el que me encontré donde necesitaba un decimal AS era cuando enviaba XML al servicio web de Amazon. El servicio se quejaba porque un valor decimal (originalmente de SQL Server) se estaba enviando como 25.1200rechazado, (25.12 era el formato esperado).

Todo lo que necesitaba hacer era Decimal.Round(...)con 2 decimales para solucionar el problema.

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

TypedValuees de tipo, Decimalasí que no podía hacerlo ToString("N2")y necesitaba redondearlo y mantenerlo como decimal.


55
+1 esta es una gran respuesta. Cuando dice que System.Decimal "sabe cuántos lugares decimales tiene", el término es que System.Decimal no se auto normaliza como los otros tipos de coma flotante. Otra propiedad útil de System.Decimal es que el resultado de las operaciones matemáticas siempre tiene el mayor número de decimales de los argumentos de entrada, es decir. 1.0m + 2.000m = 3.000m . Puede usar este hecho para forzar un decimal sin decimales a 2 decimales simplemente multiplicándolo por 1,00m, por ejemplo. 10m * 1.00m = 10.00m .
MattDavey

2
MattDavey's es incorrecto, se agrega la precisión decimal. (1.0m * 1.00m) .ToString () = "1.000"
Kaido

2
Es muy, muy útil saber que "un decimal 'sabe' cuántos decimales tiene en función de su origen". ¡Muchas gracias!
iheartcsharp

21

Aquí hay un pequeño programa de 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("===================");
}

Aquí están los 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
===================


11

Muy raramente querría una cadena vacía si el valor es 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 respuesta mejor calificada es incorrecta y ha desperdiciado 10 minutos (la mayoría) del tiempo de las personas.


1
básicamente "#"significa dígito de número (si es necesario) (sin relleno si no es necesario) "0"significa dígito de número (no importa qué) (rellenado con ceros si no está disponible)
Sr. Heelis

10

La respuesta de Mike M. fue perfecta para mí en .NET, pero .NET Core no tiene un decimal.Roundmétodo al momento de escribir.

En .NET Core, tuve que usar:

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

Un método hacky, que incluye la conversión a cadena, es:

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

Ninguno de estos hizo exactamente lo que necesitaba, forzar 2 dp y redondear como0.005 -> 0.01

Forzar 2 dp requiere aumentar la precisión en 2 dp para garantizar que tengamos al menos 2 dp

luego redondeando para asegurarnos de que no tenemos más de 2 dp

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

6.665m.ToString() -> "6.67"

6.6m.ToString() -> "6.60"

9

La respuesta mejor calificada describe un método para formatear la representación de cadena del valor decimal, y funciona.

Sin embargo, si realmente desea cambiar la precisión guardada en el valor real, debe escribir algo como lo siguiente:

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 ejemplo de prueba unitaria:

[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

Puede usar system.globalization para formatear un número en cualquier formato requerido.

Por ejemplo:

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

Si tiene un decimal d = 1.2300000y necesita recortarlo a 2 decimales, entonces puede imprimirse así d.Tostring("F2",ci);donde F2 está formando cadenas a 2 decimales y ci es la configuración regional o información cultural.

Para obtener más información, consulte este enlace
http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx


+1 pero - el objeto CultureInfo solo afectaría el carácter unicode usado para denotar el lugar decimal. p.ej. fr-FR usaría una coma en lugar de un punto. No está relacionado con el número de decimales representados.
MattDavey


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

1

Si necesita mantener solo 2 lugares decimales (es decir, cortar todo el resto de dígitos decimales):

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

Si necesita mantener solo 3 decimales:

decimal val = 3.14789m;
decimal result = Math.Floor(val * 1000) / 1000; // result = 3.147
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.