13

I've just learned that a decimal somehow remembers how much trailaing zero's were needed to store a number. With other words: it remembers the size of the fraction.

For example:

123M.ToString() ==> resuls in: 123
123.00M.ToString() ==> resuls in: 123.00
123.450M.ToString() ==> resuls in: 123.450

I am looking for a formatting string or another trick to get rid of those "unneeded" trailing zeros, but keeping the significant digits. So:

123M.ToString() ==> resuls in: 123
123.00M.ToString() ==> resuls in: 123
123.450M.ToString() ==> resuls in: 123.45

Removing the zeros at the end of the new string is not a real option for me, because then I have to find out if the string contains a fraction and if so, also have to remove the optional '.' or ',' depending on the culture, etc.

Luke Girvin
  • 13,221
  • 9
  • 64
  • 84
Martin Mulder
  • 12,642
  • 3
  • 25
  • 54
  • I think the best answer on this topic is [this one](http://stackoverflow.com/a/7983330/187697) – keyboardP Jul 07 '13 at 21:21
  • Possible duplicate of [Remove trailing zeros](http://stackoverflow.com/questions/4525854/remove-trailing-zeros), which is older and has better answers and comments. – Sam Feb 22 '17 at 00:57

3 Answers3

16

There are several ways to do it, but since you are converting to a String object anyway, I suppose you could try something like this:

myDecimalVariable.ToString("G29");

or, using your code above, assuming 123.00M is your decimal:

123.00M.ToString("G29");

Here is the explanation of how that concise example works:

The G format with a number means to format that many significant digits. Because 29 is the most significant digits that a Decimal can have, this will effectively truncate the trailing zeros without rounding.

Dan Beaulieu
  • 19,406
  • 19
  • 101
  • 135
Michael Hawkins
  • 2,793
  • 1
  • 19
  • 33
0

just apply the Format specifier zero and will remove the trailing zeros:

string test = (1.23M * 100M).ToString("0");
//prints 123.
string test2 = 123.450M.ToString(".00");
//prints 123.45.
string test3 = 123.450M.ToString().Trim('0');
terrybozzio
  • 4,424
  • 1
  • 19
  • 25
  • Note that `Trim('0')` will result in `0.5m` being formatted as `.5` rather than `0.5`. – Sam Feb 22 '17 at 00:30
0

The method below () deals with the following edge cases:

  • Input: 123.00M, expecting "123.00"
    • ❌ G29: 123
    • ✅ : 123.00
  • Input: -0.00000000001M, expecting "-0.00000000001"
    • ❌ G29: -1E-11
    • ✅ : -0.00000000001
private static string SlowButStrong(decimal v)
{
  if( v % 1 == 0) return v.ToString(); // If no decimal digits, let's leave it alone
  var withNoZeroes = v.ToString().TrimEnd('0');
  return withNoZeroes.EndsWith('.') ? withNoZeroes + "00" : withNoZeroes;
}

Test output

Input 123M, expecting 123
✅ G29: 123
✅ : 123
✅ ⛵: 123

Input 123.00M, expecting 123.00
❌ G29: 123
✅ : 123.00
❌ ⛵: 123

Input 123.45M, expecting 123.45
✅ G29: 123.45
✅ : 123.45
✅ ⛵: 123.45

Input 123.450M, expecting 123.45
✅ G29: 123.45
✅ : 123.45
✅ ⛵: 123.45

Input 5.00000001M, expecting 5.00000001
✅ G29: 5.00000001
✅ : 5.00000001
✅ ⛵: 5.00000001

Input -0.00000000001M, expecting -0.00000000001
❌ G29: -1E-11
✅ : -0.00000000001
✅ ⛵: -0.00000000001

Input 10000000000000000000000M, expecting 10000000000000000000000
✅ G29: 10000000000000000000000
✅ : 10000000000000000000000
✅ ⛵: 10000000000000000000000

Arbitrary test case

public static void Main(string[] args)
{
    Test("123M", 123M, "123");
    Test("123.00M", 123.00M, "123.00");
    Test("123.45M", 123.45M, "123.45");
    Test("123.450M", 123.450M, "123.45");
    Test("5.00000001M", 5.00000001M, "5.00000001");
    Test("-0.00000000001M", -0.00000000001M, "-0.00000000001");
    Test("10000000000000000000000M", 10000000000000000000000M, "10000000000000000000000");
}

private static void Test(string vs, decimal v, string expected)
{
    Console.OutputEncoding = System.Text.Encoding.UTF8;

    Console.WriteLine($"Input {vs}, expecting {expected}");
    Print("G29", v.ToString("G29"), expected);
    Print("", SlowButStrong(v), expected);
    Print("⛵", LessSlowButStrong(v), expected);
    Console.WriteLine();
}

private static void Print(string prefix, string formatted, string original)
{
    var mark = formatted == original ? "✅" : "❌"; 
    Console.WriteLine($"{mark} {prefix:10}: {formatted}");
}

private static string SlowButStrong(decimal v)
{
    if( v % 1 == 0) return v.ToString(); // If no decimal digits, let's leave it alone
    var withNoZeroes = v.ToString().TrimEnd('0');
    return withNoZeroes.EndsWith('.') ? withNoZeroes + "00" : withNoZeroes;
}

private static string LessSlowButStrong(decimal v)
{
    return v.ToString((v < 1) ? "" : "G29");
}
tymtam
  • 31,798
  • 8
  • 86
  • 126