815

When displaying the value of a decimal currently with .ToString(), it's accurate to like 15 decimal places, and since I'm using it to represent dollars and cents, I only want the output to be 2 decimal places.

Do I use a variation of .ToString() for this?

Liam
  • 27,717
  • 28
  • 128
  • 190
wows
  • 10,687
  • 7
  • 27
  • 27
  • 1
    [Here](https://stackoverflow.com/a/58733847/2093077) is a brief example of the different options for formatting floating point values (alignment, number of digits, group separators, exponential, percent, currency, etc.). – saastn Mar 01 '21 at 23:33
  • Does this answer your question? [Using String Format to show decimal up to 2 places or simple integer](https://stackoverflow.com/questions/6951335/using-string-format-to-show-decimal-up-to-2-places-or-simple-integer) – Harish Nov 09 '21 at 05:25

19 Answers19

1162
decimalVar.ToString("#.##"); // returns ".5" when decimalVar == 0.5m

or

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

or

decimalVar.ToString("0.00"); // returns "0.50"  when decimalVar == 0.5m
Rudey
  • 4,717
  • 4
  • 42
  • 84
albertein
  • 26,396
  • 5
  • 54
  • 57
  • 40
    the problem here is when we have 0.00; it returns an empty string. – Jronny May 04 '10 at 10:13
  • 178
    Then you could do decimalVar.ToString ("0.##"). You can also use 0.00 as the formatting string. – albertein May 04 '10 at 15:14
  • @MikeCole I don't think you can perform truncation with just formatting alone -- the only way I know is to pass it into Math.Floor first, so something like (Math.Floor(decimalVar * 100M) / 100M).ToString("0.00") should work (and if you're using doubles and not decimals use 100D instead of 100M, of course). – BrainSlugs83 Aug 26 '13 at 09:50
  • 70
    With this solution, you won't have the culture formatting that one would expect when reading numbers. For this you should use ToString("N2"), or ToString("N"). – Shautieh Aug 21 '14 at 15:54
  • 1
    This is a very misleading answer. This just creates a new string, Yet the number value remains unchanged. This creates havoc anywhere else this number is consumed. It is a seroius issu not be able to downgrade type decimal to some number of decimal places. – f470071 Oct 02 '15 at 12:13
  • 2
    @Hill `Decimal` and `Double` type `ToString` method accepts argument for formatting. Try converting your value to Decimal/Double first. – sohaiby Mar 13 '16 at 08:05
  • 3
    @f470071 Decimals are value types and as such are never "modified". Regardless, ToString() has never been expected to modify the contents of whatever it is called on. – Justin Skiles Aug 26 '16 at 12:35
  • 1
    Works ok for decimals. If its an integer number then "#.##" will ignore the decimal places. However "{0:#,##0.00}" will work for both decimal and integer numbers. – Rahatur Oct 03 '16 at 19:50
  • @Hill You may get that error with nullable type. Try yourNumber.Value.ToString(0.##) to solve your problem – Anh Hoang Apr 05 '18 at 08:37
  • 1
    The solution below is better, as it deals with it as a decimal and returns decimal – Mocas Jan 23 '19 at 15:29
  • This one helped me retain the trailing decimal places. As long as you convert back to Decimal type like this: Convert.ToDecimal(costInDecimal.ToString("0.00")); – levis84 May 06 '22 at 06:40
687

I know this is an old question, but I was surprised to see that no one seemed to post an answer that;

  1. Didn't use bankers rounding
  2. Keeps the value as a decimal.

This is what I would use:

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

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

Rudey
  • 4,717
  • 4
  • 42
  • 84
Mike M.
  • 12,343
  • 1
  • 24
  • 28
451
decimalVar.ToString("F");

This will:

  • Round off to 2 decimal places eg. 23.45623.46
  • Ensure that there are always 2 decimal places eg. 2323.00; 12.512.50

Ideal for displaying currency.

Check out the documentation on ToString("F") (thanks to Jon Schneider).

fhcimolin
  • 616
  • 1
  • 8
  • 27
Sofox
  • 5,088
  • 1
  • 19
  • 10
  • 15
    This works fine when only has 1 decimal; .ToString("#.##") fails. This answer is much better – Eric Frick Mar 21 '13 at 18:25
  • 3
    Wouldn't it round 23.456 => 23.46 ? – rtpHarry May 31 '13 at 13:07
  • 19
    Documentation on what the "F" means here, and how it works: http://msdn.microsoft.com/en-us/library/dwhawy9k%28v=vs.110%29.aspx#FFormatString – Jon Schneider Jun 25 '14 at 15:06
  • 8
    Why not .ToString("N") instead of "F"? It's my understanding they'll both work for the needs of this question, but N will also put commas in for numbers in the thousands. – jgerman Sep 29 '14 at 16:30
  • 6
    Note: The `.` might be replaced with `,` based on the culture. You should pass along `CultureInfo.InvariantCulture` as the second argument to disable this. – Duncan Lukkenaer Feb 12 '19 at 15:04
  • 1
    What's the difference between "F" and "0.00"? – Rudey Aug 11 '21 at 15:23
121

If you just need this for display use string.Format

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

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

The "m" is a decimal suffix. About the decimal suffix:

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

xdumaine
  • 10,096
  • 6
  • 62
  • 103
Jorge Ferreira
  • 96,051
  • 25
  • 122
  • 132
60

If you want it formatted with commas as well as a decimal point (but no currency symbol), such as 3,456,789.12...

decimalVar.ToString("n2");
Joel Mueller
  • 28,324
  • 9
  • 63
  • 88
  • 3
    Better answer as the question was about outputting on a page, and the number formatting is important for big numbers. Also, "n*" takes into account the current culture, so it could be "3.456.789,12", "3 456 789,12", etc. – Shautieh Aug 21 '14 at 15:48
59

Given decimal d=12.345; the expressions d.ToString("C") or String.Format("{0:C}", d) yield $12.35 - note that the current culture's currency settings including the symbol are used.

Note that "C" uses number of digits from current culture. You can always override default to force necessary precision with C{Precision specifier} like String.Format("{0:C2}", 5.123d).

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
Hafthor
  • 16,358
  • 9
  • 56
  • 65
43

There's a very important characteristic of Decimal that isn't obvious:

A Decimal 'knows' how many decimal places it has based upon where it came from

The following may be unexpected :

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"

Doing the same operations with Double will result in zero decimal places ("25") for all of the above examples.

If you want a decimal to 2 decimal places there's a high likelihood it's because it's currency in which case this is probably fine for 95% of the time:

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

Or in XAML you would use {Binding Price, StringFormat=c}

One case I ran into where I needed a decimal AS a decimal was when sending XML to Amazon's webservice. The service was complaining because a Decimal value (originally from SQL Server) was being sent as 25.1200 and rejected, (25.12 was the expected format).

All I needed to do was Decimal.Round(...) with 2 decimal places to fix the problem regardless of the source of the value.

 // generated code by XSD.exe
 StandardPrice = new OverrideCurrencyAmount()
 {
       TypedValue = Decimal.Round(product.StandardPrice, 2),
       currency = "USD"
 }

TypedValue is of type Decimal so I couldn't just do ToString("N2") and needed to round it and keep it as a decimal.

Ryan Shripat
  • 5,574
  • 6
  • 49
  • 77
Simon_Weaver
  • 140,023
  • 84
  • 646
  • 689
  • 6
    +1 this is a great answer. When you say that System.Decimal "knows how many decimal places is has" - the term is that System.Decimal is not **self-normalizing** as the other floating point types are. Another useful property of System.Decimal is that the result of math operations always have the highest number of decimal places from the input arguments ie. *1.0m + 2.000m = 3.000m*. You can use this fact to force a decimal with no decimal places to 2 decimal places simply by multiplying it by 1.00m eg. *10m * 1.00m = 10.00m*. – MattDavey Jan 10 '12 at 17:16
  • 2
    MattDavey's is incorrect, the decimal precision is added. (1.0m * 1.00m).ToString() = "1.000" – Kaido Oct 25 '12 at 14:27
  • 2
    It is very, very useful to know that "A decimal 'knows' how many decimal places it has based upon where it came from." Thanks a lot! – iheartcsharp Jul 08 '13 at 18:07
  • appreciate your answer and explanation! – sspaniel Jan 28 '21 at 14:23
24

Here is a little Linqpad program to show different 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("===================");
}

Here are the results:

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
===================
What Would Be Cool
  • 6,204
  • 5
  • 45
  • 42
16

Math.Round Method (Decimal, Int32)

John Smith
  • 631
  • 1
  • 6
  • 7
16

Very rarely would you want an empty string if the value is 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"

The top rated answer is incorrect and has wasted 10 minutes of (most) people's time.

goamn
  • 1,939
  • 2
  • 23
  • 39
  • 1
    basically `"#"` means digit of number (if necessary) (without padding if not needed) `"0"` means digit of number (no mater what) (padded with zeros if not available) – Mr Heelis Jan 19 '18 at 14:09
14

Mike M.'s answer was perfect for me on .NET, but .NET Core doesn't have a decimal.Round method at the time of writing.

In .NET Core, I had to use:

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

A hacky method, including conversion to string, is:

public string FormatTo2Dp(decimal myNumber)
{
    // Use schoolboy rounding, not bankers.
    myNumber = Math.Round(myNumber, 2, MidpointRounding.AwayFromZero);

    return string.Format("{0:0.00}", myNumber);
}
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
JsAndDotNet
  • 16,260
  • 18
  • 100
  • 123
10

None of these did exactly what I needed, to force 2 d.p. and round up as 0.005 -> 0.01

Forcing 2 d.p. requires increasing the precision by 2 d.p. to ensure we have at least 2 d.p.

then rounding to ensure we do not have more than 2 d.p.

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

6.665m.ToString() -> "6.67"

6.6m.ToString() -> "6.60"
Alicia
  • 1,152
  • 1
  • 23
  • 41
Kaido
  • 3,383
  • 24
  • 34
10

The top-rated answer describes a method for formatting the string representation of the decimal value, and it works.

However, if you actually want to change the precision saved to the actual value, you need to write something like the following:

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

An example 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"));
}
Alex
  • 121
  • 1
  • 5
8

You can use system.globalization to format a number in any required format.

For example:

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

If you have a decimal d = 1.2300000 and you need to trim it to 2 decimal places then it can be printed like this d.Tostring("F2",ci); where F2 is string formating to 2 decimal places and ci is the locale or cultureinfo.

for more info check this link
http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx

Alicia
  • 1,152
  • 1
  • 23
  • 41
Smitha Poluri
  • 121
  • 2
  • 4
  • +1 but - the CultureInfo object would only affect the unicode character used to denote the decimal place. eg. fr-FR would use a comma instead of a period. It's not related to the number of decimal places rendered. – MattDavey Jan 11 '12 at 09:17
6

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

This link explains in detail how you can handle your problem and what you can do if you want to learn more. For simplicity purposes, what you want to do is

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

if you want this for a currency, you can make it easier by typing "C2" instead of "F2"

Vasfed
  • 18,013
  • 10
  • 47
  • 53
Jeff Jose
  • 131
  • 2
  • 2
6

The most applicable solution is

decimalVar.ToString("#.##");
BanukaKA
  • 88
  • 1
  • 4
4
Double Amount = 0;
string amount;
amount=string.Format("{0:F2}", Decimal.Parse(Amount.ToString()));
Code
  • 679
  • 5
  • 9
4

If you need to keep only 2 decimal places (i.e. cut off all the rest of decimal digits):

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

If you need to keep only 3 decimal places:

decimal val = 3.14789m;
decimal result = Math.Floor(val * 1000) / 1000; // result = 3.147
Aleksei Mialkin
  • 2,257
  • 1
  • 28
  • 26
1
        var arr = new List<int>() { -4, 3, -9, 0, 4, 1 };
        decimal result1 = arr.Where(p => p > 0).Count();
        var responseResult1 = result1 / arr.Count();
        decimal result2 = arr.Where(p => p < 0).Count();
        var responseResult2 = result2 / arr.Count();
        decimal result3 = arr.Where(p => p == 0).Count();
        var responseResult3 = result3 / arr.Count();
        Console.WriteLine(String.Format("{0:#,0.000}", responseResult1));
        Console.WriteLine(String.Format("{0:#,0.0000}", responseResult2));
        Console.WriteLine(String.Format("{0:#,0.00000}", responseResult3));

you can put as many 0 as you want.

ihsan güç
  • 241
  • 3
  • 7