#1,077 – The Decimal Numeral System

Humans normally represent numeric values using the decimal numeral system.  Decimal is a base 10 numeral system, which means that we use ten different digits (numeric symbols) and represent a particular number using a string of these digits.  Our ten digits are: 0, 1, 2, 3, 4, 5, 6, 7, 8, and 9.

Moving from right to left, the digits in a base 10 system represent powers of 10 (1, 10, 100, etc. or 10^0, 10^1, 10^2, etc).  The value of the number is the sum of the value of each digit multiplied by the appropriate power of 10.  For example: As an example, the number 3829 represents: three thousand (3 x 1000), eight hundred (8 x 100), and twenty (2 x 10) nine (9 x 1). #80 – Use Decimal Type for Monetary Calculations

Since floating point numbers are stored as a binary data, most floating point numbers cannot be stored exactly and suffer from round-off error–the difference between the true mathematical value and the value being stored digitally.

Because of how floating point numbers are stored, even simple base-10 numbers with not much precision cannot be represented exactly.  Consider the example below:

float f1 = 0.1f;
float error = (f1 * 1000.0f) - 100.0f;  // Error is 1.49e-6

This demonstrates that we weren’t able to store exactly the value of 0.1, but the value nearest to 0.1 that was representable using the float type.

This inaccuracy leads to errors when we try to store values representing financial transactions and perform simple mathematical operations on the values.  Because of this, you should always use the decimal type for storing financial data:

decimal f1 = 0.1m;
decimal error = (f1 * 999999999.0m) - 99999999.9m;  // Error still 0

#49 – When to Use the Decimal Type

You should use the decimal type (System.Decimal) for monetary calculations, or whenever you want more digits of precision, to avoid round-off error.

For example:

float f1 = 12345678901234567.28f;     // 1.23456784E+16
double d1 = 12345678901234567.28d;    // 12345678901234568.0
decimal dc1 = 12345678901234567.28m;  // 12345678901234567.28

The decimal type gives you greater precision, but doesn’t support storing numbers as large as float or double.  This is because it stores all digits, rather than storing the mantissa and exponent of the number.  The decimal type also requires more storage space.

float – 4 bytes  (±1.5e−45 to ±3.4e38, 7 digit precision)
double – 8 bytes  (±5.0e−324 to ±1.7e308, 15-16 digit precision)
decimal – 16 bytes  (±1.0 × 10−28 to ±7.9 × 1028, 28-29 digit precision)