我使用哪种Swift数据类型作为货币

Peo*_*mer 21 ios swift

我有一个iOS应用程序,将对代表美元货币的数字执行大量基本算术(例如25.00代表25.00美元).

我在使用Java和Javascript等其他语言的数据类型Double时遇到了很多麻烦,所以我想知道在Swift中用于货币的最佳数据类型.

rob*_*off 25

使用NSDecimalNumber(这里有更多信息).例:

let a = NSDecimalNumber(integer: 123456)
let b = NSDecimalNumber(integer: 1000)
let c = a.decimalNumberByDividingBy(b)
println(c)
// Result: "123.456"
Run Code Online (Sandbox Code Playgroud)

您可能希望使用类似这样的扩展来向NSDecimalNumber该类添加运算符重载.

  • 当"NSDecimalNumber"和"NSNumberFormatter"已经知道如何正确地进行十进制算术和货币格式化时,为什么"只是"制作Money类?[引入一些运算符重载](https://gist.github.com/mattt/1ed12090d7c89f36fd28),你就完成了. (4认同)
  • 对于_currency_来说,这是一个“可怕的”解决方案,因为用“Double”初始化“Decimal”很容易导致舍入错误。例如:`十进制(2.13)== 2.129999999999999488` (3认同)
  • 我的回答并不建议从“Double”转换为“Decimal”。我的答案展示了如何通过除以 10 的幂来准确创建带有小数位的“小数”。 (2认同)

Eri*_*ric 11

使用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 
}
Run Code Online (Sandbox Code Playgroud)

不正确

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  
}
Run Code Online (Sandbox Code Playgroud)

对表示货币金额的Doubles或Floats 进行算术运算将产生不正确的结果。这是因为DoubleFloat类型不能准确表示大多数十进制数字。更多信息在这里

底线: 使用Decimal或来对货币金额执行算术运算Int


fpg*_*503 6

有一个非常不错的库,名为Money

let money: Money = 100
let moreMoney = money + 50 //150
Run Code Online (Sandbox Code Playgroud)

除此之外,还有很多不错的功能,例如类型安全的货币:

let euros: EUR = 100
let dollars: USD = 1500
euros + dollars //Error
Run Code Online (Sandbox Code Playgroud)

二进制运算符'+'不能应用于类型'EUR'(aka'_Money')和'USD'(aka'_Money')的操作数

  • 此类警告:它不符合 NSCoding,这意味着您将无法使用 NSCoder 保存 Money 类型的值。Xcode 会抛出错误。 (2认同)