// thinkbeforecoding

Decimal, what are those trailing zeros ?

2009-05-07T10:24:17 / jeremie chassaing

Yesterday, I stumbled on something I didn’t expect at all…

An exception appeared while testing my code that I had been carefully writing following Design By Example..

Looking in my debugger my decimal two variables had value 4M.

But calling ToString on it led to different results : “4” and “4.00”…

What the heck ?! How come ?

 

I should have known this

Yes, the MSDN state it explicitly :

The scaling factor also preserves any trailing zeroes in a Decimal number. Trailing zeroes do not affect the value of a Decimal number in arithmetic or comparison operations. However, trailing zeroes can be revealed by the ToString method if an appropriate format string is applied.

And I did not know that, did you ?

 

Try it yourself

you can try it yourself :

Console.WriteLine(1m);      // 1
Console.WriteLine(1.0m);    // 1.0
Console.WriteLine(1.00m);   // 1.00

Console.WriteLine(1m == 1.0m); // true
Console.WriteLine(1m.ToString() == 1.0m.ToString()); // false

The decimal.Parse function also preserve trailing zeros :

Console.WriteLine(decimal.Parse("1.0", CultureInfo.InvariantCulture)); // 1.0
Console.WriteLine(decimal.Parse("1.000", CultureInfo.InvariantCulture)); // 1.000

 

The explanation

The decimal type internally represents values using an 96 bit integer and a negative power of 10 (between 0 and 28).

Those values are simply internally stored like this :

1.0 –> 10 * 10^-1
1.000 –> 1000 * 10^-3

You can check it using the decimal.GetBits method.

The trailing zeros are even maintained in arithmetical operations :

Console.WriteLine(2.0m * 3.00m);  // 6.000

But are handled correctly by the equality and comparison methods :

Console.WriteLine(1m == 1.0m);  // true
Console.WriteLine(1m.GetHashCode() == 1.0m.GetHashCode()); // true

 

Do you know other secrets like this ?

Of course, my unit tests did not test case I didn’t expect to happen !

But, Hey ! If you knew it, you should have told me before !

What secret feature/behavior in the .Net framework or in the C# language do you know ?