我有一个iOS应用程序,它会对代表美元货币的数字执行大量基本算术运算(例如25.00代表25.00美元)。
我在使用Java和Javascript等其他语言的数据类型Double时遇到了很多麻烦,所以我想知道在Swift中用于货币的最佳数据类型。
答案 0 :(得分:23)
使用NSDecimalNumber
(more info here)。例如:
let a = NSDecimalNumber(integer: 123456)
let b = NSDecimalNumber(integer: 1000)
let c = a.decimalNumberByDividingBy(b)
println(c)
// Result: "123.456"
您可能希望使用an extension like this one将运算符重载添加到NSDecimalNumber
类。
答案 1 :(得分:5)
有一个非常好的名为Money的lib:
let money: Money = 100
let moreMoney = money + 50 //150
除此之外还有许多不错的功能,例如类型安全的货币:
let euros: EUR = 100
let dollars: USD = 1500
euros + dollars //Error
二进制运算符'+'不能应用于'EUR'(又名'_Money')和'USD'(又名'_Money')
类型的操作数
答案 2 :(得分:5)
使用Decimal
,并确保正确初始化它!
// 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
}
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
}
在代表货币金额的Double
或Float
上执行算术运算将产生不正确的结果。是因为Double
和Float
类型不能准确表示大多数十进制数字。 More information here。
底线:
使用Decimal
或Int
答案 3 :(得分:0)
Flight-School/Money 可能是资金充裕的项目的最佳选择。
在 ending of README 中,@mattt 为简单的 Money 类型提供了一个很好的解决方案:
struct Money {
enum Currency: String {
case USD, EUR, GBP, CNY // supported currencies here
}
var amount: Decimal
var currency: Currency
}
“Flight School Guide to Swift Numbers”中的第 3 章提供了对该主题的出色介绍。
答案 4 :(得分:0)
我们使用这种方法,Currency
是一个预先生成的巨大枚举(不要忘记货币值只是一个没有货币的数字 - 它们都属于一起):
struct Money: Hashable, Equatable {
let value: Decimal
let currency: Currency
}
extension Money {
var string: String {
CurrencyFormatter.shared.string(from: self)
}
}