See Also: Decimal Members
The decimal type can represent values with at least 28 significant digits. The decimal data type is ideally suited to financial calculations that require a large number of significant digits and no round-off errors.
The decimal type shall represent values in at least the range -79228162514264337593543950335 to 79228162514264337593543950335, and having scale f such that 0 <= f <= at least 28.
A decimal value occupies 128 bits; however, its representation is unspecified (see note below).
The result of an operation on values of type decimal is that which would result from calculating an exact result (preserving scale, as defined for each operator) and then rounding to fit the representation. That is, results are exact to at least 28 digits, but not necessarily to more than 28 decimal places. A zero result has a sign of 0.
Results are rounded to the nearest representable value, and, when a result is equally close to two representable values, to the value that has an even number in the least significant digit position (banker's rounding).
The default initial value of an instance of type decimal is zero with a scale of zero.
Unlike the float and double data types, decimal fractional numbers such as 0.1 can be represented exactly in the decimal representation. In the float and double representations, such numbers are often infinite fractions, making those representations prone to round-off errors.
Further, the decimal representation preserves scale, so that 1.23 + 1.27 will give the answer 2.50, not 2.5.
If a decimal arithmetic operation produces a value that is too small for the decimal format after rounding, the result of the operation is zero. If a decimal arithmetic operation produces a result that is too large for the decimal format, a OverflowException is thrown.
The decimal class implements implicit conversions from the sbyte, byte, short, ushort, int, uint, long, and ulong types to decimal. These implicit conversions never lose information and never throw exceptions. The decimal class also implements explicit conversions from decimal to byte, sbyte, short, ushort, int, uint, long, and ulong. These explicit conversions round the decimal value towards zero to the nearest integer, and then convert that integer to the destination type. A OverflowException is thrown if the result is not within the range of the destination type.
The decimal class provides narrowing conversions to and from the float and double types. A conversion from decimal to float or double can lose precision. If the value being converted is not within the range of the destination type, a OverflowException is thrown. A conversion from float or double to decimal throws a OverflowException if the value is not within the range of the decimal type.
Although different implementations of decimal can have different representations, interchange of a decimal value within the range of the internal format can still be achieved by converting it to a string, exporting it, and then converting it back to internal format.
In Version 1 of this standard, the representation of decimal was well-defined, as follows.
When considered as an array of four ints, it contains the following four elements:
Index 0 (bits 0-31) contains the low-order 32 bits of the decimal's coefficient.
Index 1 (bits 32-63) contains the middle 32 bits of the decimal's coefficient.
Index 2 (bits 64-95) contains the high-order 32 bits of the decimal's coefficient.
Index 3 (bits 96-127) contains the sign bit and scale, as follows:
|16-23||Scale||Contains a value between 0 and 28.|
|31||Sign||0 (positive) or 1 (negative).|
In order to allow alternate representations (such as in the update to the IEC floating-point standard, IEC-60559, currently in preparation), the representation has been made unspecified.