# with - Difference between decimal, float and double in.NET?

## float vs double example (11)

What is the difference between `decimal`

, `float`

and `double`

in .NET?

When would someone use one of these?

https://code.i-harness.com

- Double and float can be divided by integer zero without an exception at both compilation and run time.
- Decimal cannot be divided by integer zero. Compilation will always fail if you do that.

`float`

7 digits of precision

`double`

has about 15 digits of precision

`decimal`

has about 28 digits of precision

If you need better accuracy, use double instead of float. In modern CPUs both data types have almost the same performance. The only benifit of using float is they take up less space. Practically matters only if you have got many of them.

I found this is interesting. What Every Computer Scientist Should Know About Floating-Point Arithmetic

For applications such as games and embedded systems where memory and performance are both critical, float is usually the numeric type of choice as it is faster and half the size of a double. Integers used to be the weapon of choice, but floating point performance has overtaken integer in modern processors. Decimal is right out!

I won't reiterate tons of good (and some bad) information already answered in other answers and comments, but I will answer your followup question with a tip:

When would someone use one of these?

Use decimal for **counted** values

Use float/double for **measured** values

Some examples:

money (do we count money or measure money?)

distance (do we count distance or measure distance? *)

scores (do we count scores or measure scores?)

We always count money and should never measure it. We usually measure distance. We often count scores.

* In some cases, what I would call *nominal distance*, we may indeed want to 'count' distance. For example, maybe we are dealing with country signs that show distances to cities, and we know that those distances never have more than one decimal digit (xxx.x km).

Integers, as was mentioned, are whole numbers. They can't store the point something, like .7, .42, and .007. If you need to store numbers that are not whole numbers, you need a different type of variable. You can use the double type or the float type. You set these types of variables up in exactly the same way: instead of using the word `int`

, you type `double`

or `float`

. Like this:

```
float myFloat;
double myDouble;
```

(`float`

is short for "floating point", and just means a number with a point something on the end.)

The difference between the two is in the size of the numbers that they can hold. For `float`

, you can have up to 7 digits in your number. For `double`

s, you can have up to 16 digits. To be more precise, here's the official size:

```
float: 1.5 × 10^-45 to 3.4 × 10^38
double: 5.0 × 10^-324 to 1.7 × 10^308
```

`float`

is a 32-bit number, and `double`

is a 64-bit number.

Double click your new button to get at the code. Add the following three lines to your button code:

```
double myDouble;
myDouble = 0.007;
MessageBox.Show(myDouble.ToString());
```

Halt your program and return to the coding window. Change this line:

```
myDouble = 0.007;
myDouble = 12345678.1234567;
```

Run your programme and click your double button. The message box correctly displays the number. Add another number on the end, though, and C# will again round up or down. The moral is if you want accuracy, be careful of rounding!

No one has mentioned that

In default settings, Floats (System.Single) and doubles (System.Double) will never use overflow checking while Decimal (System.Decimal) will always use overflow checking.

I mean

```
decimal myNumber = decimal.MaxValue;
myNumber += 1;
```

throws **OverflowException**.

But these do not:

```
float myNumber = float.MaxValue;
myNumber += 1;
```

&

```
double myNumber = double.MaxValue;
myNumber += 1;
```

The Decimal structure is strictly geared to financial calculations requiring accuracy, which are relatively intolerant of rounding. Decimals are not adequate for scientific applications, however, for several reasons:

- A certain loss of precision is acceptable in many scientific calculations because of the practical limits of the physical problem or artifact being measured. Loss of precision is not acceptable in finance.
- Decimal is much (much) slower than float and double for most operations, primarily because floating point operations are done in binary, whereas Decimal stuff is done in base 10 (i.e. floats and doubles are handled by the FPU hardware, such as MMX/SSE, whereas decimals are calculated in software).
- Decimal has an unacceptably smaller value range than double, despite the fact that it supports more digits of precision. Therefore, Decimal can't be used to represent many scientific values.

The Decimal, Double, and Float variable types are different in the way that they store the values. Precision is the main difference where float is a single precision (32 bit) floating point data type, double is a double precision (64 bit) floating point data type and decimal is a 128-bit floating point data type.

Float - 32 bit (7 digits)

Double - 64 bit (15-16 digits)

Decimal - 128 bit (28-29 significant digits)

More about...the difference between Decimal, Float and Double

The problem with all these types is that a certain imprecision subsists AND that this problem can occur with small decimal numbers like in the following example

```
Dim fMean as Double = 1.18
Dim fDelta as Double = 0.08
Dim fLimit as Double = 1.1
If fMean - fDelta < fLimit Then
bLower = True
Else
bLower = False
End If
```

Question: Which value does bLower variable contain ?

Answer: On a 32 bit machine bLower contains TRUE !!!

If I replace Double by Decimal, bLower contains FALSE which is the good answer.

In double, the problem is that fMean-fDelta = 1.09999999999 that is lower that 1.1.

Caution: I think that same problem can certainly exists for other number because Decimal is only a double with higher precision and the precision has always a limit.

In fact, Double, Float and Decimal correspond to BINARY decimal in COBOL !

It is regrettable that other numeric types implemented in COBOL don't exist in .Net. For those that don't know COBOL, there exist in COBOL following numeric type

```
BINARY or COMP like float or double or decimal
PACKED-DECIMAL or COMP-3 (2 digit in 1 byte)
ZONED-DECIMAL (1 digit in 1 byte)
```

This has been an interesting thread for me, as today, we've just had a nasty little bug, concerning `decimal`

having less precision than a `float`

.

In our C# code, we are reading numeric values from an Excel spreadsheet, converting them into a `decimal`

, then sending this `decimal`

back to a Service to save into a *SQL Server* database.

```
Microsoft.Office.Interop.Excel.Range cell = …
object cellValue = cell.Value2;
if (cellValue != null)
{
decimal value = 0;
Decimal.TryParse(cellValue.ToString(), out value);
}
```

Now, for *almost all* of our Excel values, this worked beautifully. But for some, very small Excel values, using ** decimal.TryParse** lost the value completely. One such example is

cellValue =

**0.00006317592***Decimal.TryParse(cellValue.ToString(), out value);*// would return**0**

The solution, bizarrely, was to convert the Excel values into a `double`

first, and then into a `decimal`

:

```
Microsoft.Office.Interop.Excel.Range cell = …
object cellValue = cell.Value2;
if (cellValue != null)
{
double valueDouble = 0;
double.TryParse(cellValue.ToString(), out valueDouble);
decimal value = (decimal) valueDouble;
…
}
```

Even though `double`

has less precision than a `decimal`

, this actually ensured small numbers would still be recognised. For some reason, ** double.TryParse** was actually able to retrieve such small numbers, whereas

**would set them to zero.**

`decimal.TryParse`

Odd. Very odd.

```
+---------+----------------+---------+----------+---------------------------------------------+
| C# | .Net Framework | Signed? | Bytes | Possible Values |
| Type | (System) type | | Occupied | |
+---------+----------------+---------+----------+---------------------------------------------+
| sbyte | System.Sbyte | Yes | 1 | -128 to 127 |
| short | System.Int16 | Yes | 2 | -32768 to 32767 |
| int | System.Int32 | Yes | 4 | -2147483648 to 2147483647 |
| long | System.Int64 | Yes | 8 | -9223372036854775808 to 9223372036854775807 |
| byte | System.Byte | No | 1 | 0 to 255 |
| ushort | System.Uint16 | No | 2 | 0 to 65535 |
| uint | System.UInt32 | No | 4 | 0 to 4294967295 |
| ulong | System.Uint64 | No | 8 | 0 to 18446744073709551615 |
| float | System.Single | Yes | 4 | Approximately ±1.5 x 10-45 to ±3.4 x 1038 |
| | | | | with 7 significant figures |
| double | System.Double | Yes | 8 | Approximately ±5.0 x 10-324 to ±1.7 x 10308 |
| | | | | with 15 or 16 significant figures |
| decimal | System.Decimal | Yes | 12 | Approximately ±1.0 x 10-28 to ±7.9 x 1028 |
| | | | | with 28 or 29 significant figures |
| char | System.Char | N/A | 2 | Any Unicode character (16 bit) |
| bool | System.Boolean | N/A | 1 / 2 | true or false |
+---------+----------------+---------+----------+---------------------------------------------+
```

For more information, see:

http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/921a8ffc-9829-4145-bdc9-a96c1ec174a5