我正在尝试找出在 Swift 中将十进制数字格式化为货币值的正确方法。
例如,如果 Decimal 包含值 25.1,我希望将其打印为“$25.10”。如果它的值为 25,我想要“$25.00”。如果它碰巧包含像 25.4575 这样的值,我想将其四舍五入并显示“$25.46”。
围绕小数和字符串格式有大量令人困惑的函数。我知道我不能像使用浮点数和双精度数那样只使用 String(format: "%.2f", value) 。
Decimal 似乎有一个新的 FormatStyle 属性,但我还不能使用它,因为它需要 iOS 15。
谢谢,弗兰克
NSNumberFormatter 有货币样式,但要小心使用:
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .currency
// numberFormatter.roundingMode = .halfEven // default (bankers rounding). Available: .halfUp (schoolbook), .halfDown, .ceiling, .floor, .up, .down
let num1 = Decimal(25.0)
print(numberFormatter.string(for: num1) as Any) // Optional("$25.00")
let num2 = Decimal(25.455)
print(numberFormatter.string(for: num2) as Any) // Optional("$25.46")
let num3 = Decimal(25.445)
print(numberFormatter.string(for: num3) as Any) // Optional("$25.44")
/// ⚠️Initialize the decimal carefully because the value can be inaccurate:
let imprecise = Decimal(15.335)// ⛔️
/// > Tip: Float literal is a Double by default in Swift
print(imprecise) // 15.335000000000004096
/// To avoid this, use Decimal(string:)
var precise = Decimal(string: "15.335")! // ✅
print(precise) // 15.335
/// ⚠️ numberFormatter can have rounding error (imprecision):
print(numberFormatter.string(for: precise) as Any) // Optional("$15.33") ⛔️ Should be 15.34
/// To avoid this, you need to use NSDecimalRound before using numberFormatter:
var result = Decimal()
var copyOfPrecise = precise
NSDecimalRound(&result, ©OfPrecise, 2, .bankers) // .bankers is NSDecimalNumber.RoundingMode, you also have: .down, .up, .plain
print(result) // 15.34 ✅
print(numberFormatter.string(for: result) as Any) // ✅Optional("$15.34")
import Foundation