Contents

Purpose

Audience

What is floating point number?

Types of floating point number in C#

System.Single (float)

System.Double (double)

System.Decimal (decimal)

Caveats of floating number

Comparing results of double and decimal operations.

Comparing performance of binary and decimal floating number

When to use decimal?
This article compares the pros and cons of using different floating numbers and discusses when to use what. It stresses upon the implications of using floating numbers and what can go wrong in calculations if not used judiciously.
All the .Net developers (could by applicable to other technology base too).
Floating point number is required for representing the noninteger numbers. Floating numbers is composed of mantissa and exponent and sign. It can represented as base of 2 for binary floating number or as base of 10 for decimal floating number.
Given Mantissa => m, Exponenet => e and Base => b:
a floating number value can be represented as
mxb^{e}.
For example 51.2 can be represented as 5.12x10^{1 }while 5120 will be represented as 5.12x10^{2} as base of 10.
To represent the 51.2 as base of 2, it will be represented as
110011.0011001100110011……. =~ 110011.00110011x2^{0 }(Approx)^{ }= 1.1001100110011x2^{5}.
So we see that there cannot be exact representation of a number in binary floating number.
These are binary floating number represent in 32 bits with 1 bit for sign, 23 bits for mantissa and 8 bits for exponent.
These are binary floating number represent in 64 bits with 1 bit for sign, 52 bits for mantissa and 11 bits for exponent.
Decimal in .Net is represented by 128 bits, where 96 bits are used for mantissa, 5 bits are used for exponent whose value can range from 0 to 28 and 1 bit for sign. As we see the mantissa size is much bigger in decimal as compared to float and decimal, it has higher precision than any binary floating numbers in .Net.
If we have to store 51.2 in floating number as base of 2, the mantissa has recurring digits in the pattern of 00110011. This cannot fit into 23 bits mantissa for float or 52 bits mantissa of double. So the numbers stored in float and double are generally approximations of the numbers it intends to display.
Now we understand this let us look at what can go wrong.
Let us execute simple code using double variables:
double a = 1001.23;
double b = 1000.37;
double difference = a  b;
if(difference == 0.86)
{
Console.WriteLine("Double operations gives accurate result.");
}
else
{
Console.WriteLine("Data lost in Approximation.");
}
Against the convention the code executes the else part of ifelse block since the value of
difference != 0.86.
Now let us execute the same logic using decimal
decimal a = 1001.23m;
decimal b = 1000.37m;
decimal difference = a  b;
if (difference == 0.86m)
{
Console.WriteLine("Decimal operations gives accurate result.");
}
else
{
Console.WriteLine("Data lost in Approximation.");
}
Here the code executes if part of ifelse block meaning that difference = 0.86.
Similarly when use binary floating numbers we end up crediting/debiting wrong amount of money from an account when working in application related to finance.
Please note Decimal numbers are still not perfect in representing all the real numbers like 1/3.
Usage of decimal comes with a disadvantage of poor performance when compared to float and double. Reason being number of bits involved is more in decimal and fewer in binary floating numbers. Also binary floating numbers are hardware accelerated by using IEEE 754:1985 while decimal floating numbers hardware standard came after 23 years in IEEE 754:2008 which is yet to catch up with hardware industry.
As we see that decimal are more accurate than double and float, we may be tempted to use decimal for all the calculations in the program. As seen above decimal operations are slower than binary floating numbers we need to be judicious.
As a general convention when we have to compare equality, one should avoid float and double as it can give unpredictable results. However in greater or lesser than comparisons it is safe to use binary floating numbers.
When calculation is involved with money, some physics equation where the accuracy of data is prime importance use decimal.
When in doubt use decimal over binary floating numbers because it is better to create accurate but slow application then to create fast but inaccurate application. After that look at the performance requirement and refactor the code.