Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is the "decimal" type in C# binary-coded-decimal?

I want to handle prices in decimal currency (EUR) using C# without worrying about rounding errors and without rolling my own way of doing decimal arithmetic. The C# reference for the decimal type says

Compared to floating-point types, the decimal type has more precision and a smaller range, which makes it appropriate for financial and monetary calculations.

What?

I don't give a damn about precision, I only want about seven sig-figs. But I want to know that 5.31 EUR is an exact value. A, binary-coded-decimal type would be ideal. So my question is whether the C# decimal is that type.

like image 776
Adrian Ratnapala Avatar asked Dec 09 '22 08:12

Adrian Ratnapala


1 Answers

No, it's not BCD (where each digit is individually encoded in a specific number of bits) - but you don't want it to be. (And I certainly never claimed it was.)

decimal is a floating point type in that it has a significand and an exponent, both integers - it's just that unlike float and double, the "point" that gets shifted by the exponent is a decimal point rather than a binary point. It's unfortunate that MSDN says "compared with floating point types" when it really means "compared with binary floating point types".

The decimal documentation does actually make it reasonably clear though:

A decimal number is a floating-point value that consists of a sign, a numeric value where each digit in the value ranges from 0 to 9, and a scaling factor that indicates the position of a floating decimal point that separates the integral and fractional parts of the numeric value.

The binary representation of a Decimal value consists of a 1-bit sign, a 96-bit integer number, and a scaling factor used to divide the 96-bit integer and specify what portion of it is a decimal fraction. The scaling factor is implicitly the number 10, raised to an exponent ranging from 0 to 28. Therefore, the binary representation of a Decimal value the form, ((-296 to 296) / 10(0 to 28)), where -(296-1) is equal to MinValue, and 296-1 is equal to MaxValue. For more information about the binary representation of Decimal values and an example, see the Decimal(Int32[]) constructor and the GetBits method.

like image 138
Jon Skeet Avatar answered Dec 11 '22 09:12

Jon Skeet