Handling money in software is a task that requires precision, especially when dealing with fractions of currency like dollars and cents. One common mistake that developers make is using floating-point data types, such as `Double`

, to represent monetary values. This post explains why this is problematic and what alternatives you should use.

*Avoid Floating-Point for Monetary Values*

## The Problem with Floating-Point Arithmetic

Floating-point values, including the `Double`

type in Swift, should be avoided when working with currency amounts that have fractions. The fundamental issue is that floating-point types cannot represent certain decimal values exactly due to their binary nature.

### Example Showing Unexpected Results

Consider the following example where you want to store 0.1 dollars:

```
var balance: Double = 0.0
for _ in 1...10{
balance += 0.1
}
for _ in 1...10{
balance -= 0.1
}
print(balance) // Outputs: 2.7755575615628914e-17
```

Here, the expected value is *0.0* but we get *2.7755575615628914e-17* since value *0.1* is not stored precisely as *0.1* but as an approximation (e.g., *0.10000000149…*). This small difference can have significant consequences, especially when performing multiple arithmetic operations.

## Loss of Significance

When performing a series of arithmetic operations using floating-point numbers, you may encounter a problem known as **loss of significance**. This occurs when the precision errors from approximations accumulate, leading to larger errors that can affect the outcome of your calculations.

Let’s consider a scenario where you repeatedly add 0.1 dollars to an account balance:

```
var balance: Double = 0.0
for _ in 1...100 {
balance += 0.1
}
print(balance) // Outputs: 9.9999999999999999
```

Instead of getting the expected *10.0*, the result is slightly off due to accumulated floating-point errors. This can be particularly troublesome in financial applications where accuracy is critical.

## The Correct Approach: Use Decimal or NSDecimalNumber

To avoid the pitfalls of floating-point arithmetic, you should use the `Decimal`

type in Swift, which is designed for precise decimal arithmetic. The `Decimal`

type can represent numbers exactly as they appear, making it suitable for financial calculations.

### Example: Using Decimal

Here’s how you can correctly handle monetary values using `Decimal`

:

```
let myBalance: Decimal = 12.333
let result = myBalance / 3
print(result) // Outputs: 4.111
```

In this example, the division operation yields the expected result with no loss of precision.

### Converting Double to Decimal

If you need to work with a value initially stored as a `Double`

, you can convert it to a `Decimal`

using `NSNumber`

:

```
let doubleValue: Double = 12.333
let decimalValue: Decimal = NSNumber(floatLiteral: doubleValue).decimalValue
let result = decimalValue / 3
print(result) // Outputs: 4.111
```

By converting to `Decimal`

, you can ensure that your calculations are accurate and free from the issues associated with floating-point arithmetic.

## Conclusion

When it comes to monetary calculations, accuracy is paramount. The floating-point types, including `Double`

, should be avoided due to their inherent imprecision. Instead, use `Decimal`

or `NSDecimalNumber`

to ensure that your financial calculations are accurate and reliable. This small change can save you from potential bugs and errors in your applications, especially those dealing with money.