如何在 Swift 中将十进制数字格式化为货币? [重复]

问题描述 投票:0回答:1

我正在尝试找出在 Swift 中将十进制数字格式化为货币值的正确方法。

例如,如果 Decimal 包含值 25.1,我希望将其打印为“$25.10”。如果它的值为 25,我想要“$25.00”。如果它碰巧包含像 25.4575 这样的值,我想将其四舍五入并显示“$25.46”。

围绕小数和字符串格式有大量令人困惑的函数。我知道我不能像使用浮点数和双精度数那样只使用 String(format: "%.2f", value) 。

Decimal 似乎有一个新的 FormatStyle 属性,但我还不能使用它,因为它需要 iOS 15。

谢谢,弗兰克

swift decimal
1个回答
1
投票

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, &copyOfPrecise, 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
© www.soinside.com 2019 - 2024. All rights reserved.