Which Swift datatype do I use for currency
Use Decimal
, and make sure you initialize it properly!
CORRECT
// Initialising a Decimal from a Double:
let monetaryAmountAsDouble = 32.111
let decimal: Decimal = NSNumber(floatLiteral: 32.111).decimalValue
print(decimal) // 32.111 ð
let result = decimal / 2
print(result) // 16.0555 ð
// Initialising a Decimal from a String:
let monetaryAmountAsString = "32,111.01"
let formatter = NumberFormatter()
formatter.locale = Locale(identifier: "en_US")
formatter.numberStyle = .decimal
if let number = formatter.number(from: monetaryAmountAsString) {
let decimal = number.decimalValue
print(decimal) // 32111.01 ð
let result = decimal / 2.1
print(result) // 15290.9571428571428571428571428571428571 ð
}
INCORRECT
let monetaryAmountAsDouble = 32.111
let decimal = Decimal(monetaryAmountAsDouble)
print(decimal) // 32.11099999999999488 ð
let monetaryAmountAsString = "32,111.01"
if let decimal = Decimal(string: monetaryAmountAsString, locale: Locale(identifier: "en_US")) {
print(decimal) // 32 ð
}
Performing arithmetic operations on Double
s or Float
s representing currency amounts will produce inaccurate results. This is because the Double
and Float
types cannot accurately represent most decimal numbers. More information here.
Bottom line:
Perform arithmetic operations on currency amounts using Decimal
s or Int
I suggest you start with a typealias
for Decimal
. Example:
typealias Dollars = Decimal
let a = Dollars(123456)
let b = Dollars(1000)
let c = a / b
print(c)
Output:
123.456
If you are trying to parse a monetary value from a string, use a NumberFormatter
and set its generatesDecimalNumbers
property to true
.