Best way to display decimal without trailing zeroes

109,868

Solution 1

Do you have a maximum number of decimal places you'll ever need to display? (Your examples have a max of 5).

If so, I would think that formatting with "0.#####" would do what you want.

    static void Main(string[] args)
    {
        var dList = new decimal[] { 20, 20.00m, 20.5m, 20.5000m, 20.125m, 20.12500m, 0.000m };

        foreach (var d in dList)
            Console.WriteLine(d.ToString("0.#####"));
    }

Solution 2

I just learned how to properly use the G format specifier. See the MSDN Documentation. There is a note a little way down that states that trailing zeros will be preserved for decimal types when no precision is specified. Why they would do this I do not know, but specifying the maximum number of digits for our precision should fix that problem. So for formatting decimals, G29 is the best bet.

decimal test = 20.5000m;
test.ToString("G"); // outputs 20.5000 like the documentation says it should
test.ToString("G29"); // outputs 20.5 which is exactly what we want

Solution 3

This string format should make your day: "0.#############################". Keep in mind that decimals can have at most 29 significant digits though.

Examples:

? (1000000.00000000000050000000000m).ToString("0.#############################")
-> 1000000.0000000000005

? (1000000.00000000000050000000001m).ToString("0.#############################")
-> 1000000.0000000000005

? (1000000.0000000000005000000001m).ToString("0.#############################")
-> 1000000.0000000000005000000001

? (9223372036854775807.0000000001m).ToString("0.#############################")
-> 9223372036854775807

? (9223372036854775807.000000001m).ToString("0.#############################")
-> 9223372036854775807.000000001

Solution 4

This is yet another variation of what I saw above. In my case I need to preserve all significant digits to the right of the decimal point, meaning drop all zeros after the most significant digit. Just thought it would be nice to share. I cannot vouch for the efficiency of this though, but when try to achieve aesthetics, you are already pretty much damned to inefficiencies.

public static string ToTrimmedString(this decimal target)
{
    string strValue = target.ToString(); //Get the stock string

    //If there is a decimal point present
    if (strValue.Contains("."))
    {
        //Remove all trailing zeros
        strValue = strValue.TrimEnd('0');

        //If all we are left with is a decimal point
        if (strValue.EndsWith(".")) //then remove it
            strValue = strValue.TrimEnd('.');
    }

    return strValue;
}

That's all, just wanted to throw in my two cents.

Solution 5

Another solution, based on dyslexicanaboko's answer, but independent of the current culture:

public static string ToTrimmedString(this decimal num)
{
    string str = num.ToString();
    string decimalSeparator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
    if (str.Contains(decimalSeparator))
    {
        str = str.TrimEnd('0');
        if(str.EndsWith(decimalSeparator))
        {
            str = str.RemoveFromEnd(1);
        }
    }
    return str;
}

public static string RemoveFromEnd(this string str, int characterCount)
{
    return str.Remove(str.Length - characterCount, characterCount);
}
Share:
109,868
JC.
Author by

JC.

Updated on September 10, 2020

Comments

  • JC.
    JC. over 3 years

    Is there a display formatter that will output decimals as these string representations in c# without doing any rounding?

    // decimal -> string
    
    20 -> 20
    20.00 -> 20
    20.5 -> 20.5
    20.5000 -> 20.5
    20.125 -> 20.125
    20.12500 -> 20.125
    0.000 -> 0
    

    {0.#} will round, and using some Trim type function will not work with a bound numeric column in a grid.

  • Anthony Pegram
    Anthony Pegram almost 14 years
    And you can always throw an exorbitant* number of # symbols at the format. *not scientific
  • jgauffin
    jgauffin almost 14 years
    gr8. Now you only have "0.0" left. Would procuce an empty string with your code.
  • TrueWill
    TrueWill almost 14 years
    +1 - incidentally, you don't need the leading #. "0.#####" works identically. And either way, this does round away from zero (just FYI).
  • Ε Г И І И О
    Ε Г И І И О over 12 years
    Then I would suggest calling .ToString().TrimEnd('0').TrimEnd('.'). Also instead of '.' its better to have CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparat‌​or so that it works across cultures.
  • sehe
    sehe about 12 years
    This will lead to 0.00001 displayed as 1E-05 though
  • AaronLS
    AaronLS over 11 years
    @TrueWill Actually it does make a difference. d==0.1m then "0.#" renders "0.1" and "#.#" renders ".1" without the leading 0. Neither is wrong or right, just depends on what you want.
  • Ethan Reesor
    Ethan Reesor over 9 years
    @Mervin, please change your answer to reflect ΕГИІИО's comment. Your code would format 50.0m as 5, which is obviously an error.
  • Vadim
    Vadim over 9 years
    "20.00 --> 2" I think it is not good behaviour. To fix it call TrimEnd two times: TrimEnd('0'); TrimEnd(',');
  • Sevin7
    Sevin7 almost 8 years
    DO NOT USE the code written above. @VadymK is correct that its behavior is flawed. It will trim trailing zeros that are BEFORE the period if there is no period.
  • Eric Roller
    Eric Roller over 6 years
    This is the most general answer to the problem. Not sure why this isn't the default "G" format for decimal. The trailing zeros add no information. Microsoft documentation has a weird caveat for decimal: docs.microsoft.com/en-us/dotnet/standard/base-types/… However, if the number is a Decimal and the precision specifier is omitted, fixed-point notation is always used and trailing zeros are preserved.
  • nawfal
    nawfal over 5 years
    Downvoting. This will turn 20 into 2 :/
  • user2091150
    user2091150 over 4 years
    Great. Except for SqlDecimal it is CultureInfo.InvariantCulture.NumberFormat.NumberDecimalSepar‌​ator despite regional settings.