208

How do I format a Double to a String in C# so as to have only two decimal places?

If I use String.Format("{0:0.00}%", myDoubleValue) the number is then rounded and I want a simple truncate without any rounding. I also want the conversion to String to be culture sensitive.

Kyle Rosendo
  • 25,001
  • 7
  • 80
  • 118
kjv
  • 11,047
  • 34
  • 101
  • 140
  • What do you mean by "culture sensitive"? Does that mean that the outcome of the formatting must vary depending on a programmer-provided culture value? Or do you want to use whatever culture is the default for the current thread? – CesarGon Mar 16 '10 at 13:36
  • Helpful link https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-numeric-format-strings – Amir Jul 26 '22 at 21:06
  • @Amir - What about that link provides an answer to the OP's question? – Enigmativity Jul 26 '22 at 21:46

15 Answers15

247

I use the following:

double x = Math.Truncate(myDoubleValue * 100) / 100;

For instance:

If the number is 50.947563 and you use the following, the following will happen:

- Math.Truncate(50.947563 * 100) / 100;
- Math.Truncate(5094.7563) / 100;
- 5094 / 100
- 50.94

And there's your answer truncated, now to format the string simply do the following:

string s = string.Format("{0:N2}%", x); // No fear of rounding and takes the default number format
Kyle Rosendo
  • 25,001
  • 7
  • 80
  • 118
  • 3
    -1 You can do the culture-sensitive formatting in the same `string.Format` step that formats the string. See my answer below. – CesarGon Mar 16 '10 at 11:53
  • Precisely: the poster is asking for a solution that includes culture-sensitive formatting. Your answer is perfectly OK in the truncating part, but, as you well point out, "the culture changing would need to be done separately". You don't specify how to do it, so I think your answer only replies partially to the question. – CesarGon Mar 16 '10 at 12:00
  • 2
    That's great. I hope my comment doesn't look that silly now. :-) I'll change my downvote then. – CesarGon Mar 16 '10 at 12:06
  • 1
    To me it did, as the solution on the string formatting is incredibly simple, the truncation was more tricky. – Kyle Rosendo Mar 16 '10 at 12:15
  • If by "culture sensitive" the poster means that the formatting must produce a result that varies depending on a programmer-provided culture value, then your answer still fails there, because it uses the default culture. That's my assumption. But maybe we should ask him/her. My answer below does consider an explicit culture argument that is passed into the formatting code. I know it's simple, but that makes the answer *complete*. – CesarGon Mar 16 '10 at 13:35
  • By culture sensitive, I interpreted the opposite, so feel free to ask the op. They obviously got what they needed though. – Kyle Rosendo Mar 16 '10 at 13:48
  • 1
    Unfortunately your solution doesn't work out when the number is less than 1, to illustrate: 0.97, Is there any workaround for this situation? – Ali Dehghan May 28 '14 at 12:00
  • I also am running into the issue with it being less than one. I get 0.0 for my float using this method. – SolidSnake4444 Aug 21 '15 at 18:23
  • Why not just myDoubleValue.ToString("0.##"); ? – Jonny Sep 26 '18 at 07:03
  • 2
    @Jonny that won't work because it rounds - OP wants it to truncate (and not round). The difference is subtle. – BenKoshy May 05 '19 at 17:37
145

The following rounds the numbers, but only shows up to 2 decimal places (removing any trailing zeros), thanks to .##.

decimal d0 = 24.154m;
decimal d1 = 24.155m;
decimal d2 = 24.1m;
decimal d3 = 24.0m;

d0.ToString("0.##");   //24.15
d1.ToString("0.##");   //24.16 (rounded up)
d2.ToString("0.##");   //24.1  
d3.ToString("0.##");   //24

http://dobrzanski.net/2009/05/14/c-decimaltostring-and-how-to-get-rid-of-trailing-zeros/

user276648
  • 6,018
  • 6
  • 60
  • 86
Brian Ogden
  • 18,439
  • 10
  • 97
  • 176
  • 13
    This doesn't work. Try it with 0.2415999. This solutions rounds, not truncates. – BJury May 13 '15 at 15:03
  • 6
    Wow, so many up votes and yet it's using rounding. It may be necessary to point out that rounding is heading towards the closest decimal place requested, whereas truncating is chopping off after the closest decimal place requested. – mysticcoder Aug 24 '15 at 10:10
  • 7
    @mysticcoder I guess my answer gets so many upvotes because they come to the ops question in a Google search the same way I did, looking to removing trailing zeros, and not looking for the rounding desire of the ops question. I guess I should delete my answer... – Brian Ogden May 15 '16 at 21:09
  • 8
    @BrianOgden - No, please don't delete. I arrived here looking for your answer. +1 – Yogi Oct 08 '19 at 17:46
38

I suggest you truncate first, and then format:

double a = 123.4567;
double aTruncated = Math.Truncate(a * 100) / 100;
CultureInfo ci = new CultureInfo("de-DE");
string s = string.Format(ci, "{0:0.00}%", aTruncated);

Use the constant 100 for 2 digits truncate; use a 1 followed by as many zeros as digits after the decimal point you would like. Use the culture name you need to adjust the formatting result.

CesarGon
  • 15,099
  • 6
  • 57
  • 85
  • 4
    I think that instead of `new CultureInfo("de-DE")`, you should use the static property `Culture.InvariantCulture` – vchan Jul 10 '20 at 07:05
25

i use price.ToString("0.00") for getting the leading 0s

CMS
  • 3,657
  • 1
  • 27
  • 46
20

Simplest method, use numeric format strings:

double total = "43.257"
MessageBox.Show(total.ToString("F"));
  • 2
    Actually this method does round https://msdn.microsoft.com/en-us/library/dwhawy9k(v=vs.110).aspx#FFormatString – elvin Jul 31 '16 at 00:51
7

I had that problem with Xamarin Forms and solved it with this:

percent.ToString("0.##"+"%")
1iveowl
  • 1,622
  • 1
  • 18
  • 31
Diego Sanchez
  • 1,369
  • 1
  • 11
  • 5
6

How about adding one extra decimal that is to be rounded and then discarded:

var d = 0.241534545765;
var result1 = d.ToString("0.###%");

var result2 = result1.Remove(result1.Length - 1);
  • 4
    It's funny how a not working answer has 60 vote ups (as of today), and this pretty simple and bulletproof solution has only one.... – Arthur Kazykhanov Oct 26 '17 at 18:45
  • 6
    This will not work in the case that the rounding affects more than one digit above the cutoff. For example 0.199999 will end up as 0.20 with this code, instead of 0.19. – Bernem Mar 06 '18 at 04:08
  • well to be honest, if you have 0.199999 you probably want 0.20 anyways – Gaspa79 May 05 '23 at 13:50
6

The c# function, as expressed by Kyle Rozendo:

string DecimalPlaceNoRounding(double d, int decimalPlaces = 2)
{
    double factor = Math.Pow(10, decimalPlaces);
    d = d * factor;
    d = Math.Truncate(d);
    d = d / factor;
    return string.Format("{0:N" + Math.Abs(decimalPlaces) + "}", d);
}
Community
  • 1
  • 1
maxp
  • 24,209
  • 39
  • 123
  • 201
4

This is working for me

string prouctPrice = Convert.ToDecimal(String.Format("{0:0.00}", Convert.ToDecimal(yourString))).ToString();
Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
Zain Ali
  • 15,535
  • 14
  • 95
  • 108
2

I know this is a old thread but I've just had to do this. While the other approaches here work, I wanted an easy way to be able to affect a lot of calls to string.format. So adding the Math.Truncate to all the calls to wasn't really a good option. Also as some of the formatting is stored in a database, it made it even worse.

Thus, I made a custom format provider which would allow me to add truncation to the formatting string, eg:

string.format(new FormatProvider(), "{0:T}", 1.1299); // 1.12
string.format(new FormatProvider(), "{0:T(3)", 1.12399); // 1.123
string.format(new FormatProvider(), "{0:T(1)0,000.0", 1000.9999); // 1,000.9

The implementation is pretty simple and is easily extendible to other requirements.

public class FormatProvider : IFormatProvider, ICustomFormatter
{
    public object GetFormat(Type formatType)
    {
        if (formatType == typeof (ICustomFormatter))
        {
            return this;
        }
        return null;
    }

    public string Format(string format, object arg, IFormatProvider formatProvider)
    {
        if (arg == null || arg.GetType() != typeof (double))
        {
            try
            {
                return HandleOtherFormats(format, arg);
            }
            catch (FormatException e)
            {
                throw new FormatException(string.Format("The format of '{0}' is invalid.", format));
            }
        }

        if (format.StartsWith("T"))
        {
            int dp = 2;
            int idx = 1;
            if (format.Length > 1)
            {
                if (format[1] == '(')
                {
                    int closeIdx = format.IndexOf(')');
                    if (closeIdx > 0)
                    {
                        if (int.TryParse(format.Substring(2, closeIdx - 2), out dp))
                        {
                            idx = closeIdx + 1;
                        }
                    }
                    else
                    {
                        throw new FormatException(string.Format("The format of '{0}' is invalid.", format));
                    }
                }
            }
            double mult = Math.Pow(10, dp);
            arg = Math.Truncate((double)arg * mult) / mult;
            format = format.Substring(idx);
        }

        try
        {
            return HandleOtherFormats(format, arg);
        }
        catch (FormatException e)
        {
            throw new FormatException(string.Format("The format of '{0}' is invalid.", format));
        }
    }

    private string HandleOtherFormats(string format, object arg)
    {
        if (arg is IFormattable)
        {
            return ((IFormattable) arg).ToString(format, CultureInfo.CurrentCulture);
        }
        return arg != null ? arg.ToString() : String.Empty;
    }
}
BJury
  • 2,526
  • 3
  • 16
  • 27
1

To what is worth, for showing currency, you can use "C":

double cost = 1.99;
m_CostText.text = cost.ToString("C"); /*C: format as currentcy */

Output: $1.99

Roozbeh Zabihollahi
  • 7,207
  • 45
  • 39
0

You could also write your own IFormatProvider, though I suppose eventually you'd have to think of a way to do the actual truncation.

The .NET Framework also supports custom formatting. This typically involves the creation of a formatting class that implements both IFormatProvider and ICustomFormatter. (msdn)

At least it would be easily reusable.

There is an article about how to implement your own IFormatProvider/ICustomFormatter here at CodeProject. In this case, "extending" an existing numeric format might be the best bet. It doesn't look too hard.

Benny Jobigan
  • 5,078
  • 2
  • 31
  • 41
0

Following can be used for display only which uses the property of String ..

double value = 123.456789;
String.Format("{0:0.00}", value);
Md. Shafiqur Rahman
  • 2,878
  • 27
  • 24
0

Also note the CultureInformation of your system. Here my solution without rounding.

In this example you just have to define the variable MyValue as double. As result you get your formatted value in the string variable NewValue.

Note - Also set the C# using statement:

using System.Globalization;  

string MyFormat = "0";
if (MyValue.ToString (CultureInfo.InvariantCulture).Contains (CultureInfo.InvariantCulture.NumberFormat.NumberDecimalSeparator))
   {
      MyFormat += ".00";
   }

string NewValue = MyValue.ToString(MyFormat);
Brenners Daniel
  • 389
  • 5
  • 15
-1

Solution:

var d = 0.123345678; 
var stringD = d.ToString(); 
int indexOfP = stringD.IndexOf("."); 
var result = stringD.Remove((indexOfP+1)+2);

(indexOfP+1)+2(this number depend on how many number you want to preserve. I give it two because the question owner want.)

劉鎮瑲
  • 517
  • 9
  • 20