以下代码为我刚选择的一个测试用例产生了奇怪的结果。操场上的代码,然后是结果
import Cocoa
func spellDollars(_ amount: Decimal) -> String {
let fDollars = NumberFormatter()
fDollars.numberStyle = NumberFormatter.Style.spellOut
let fCents = NumberFormatter()
fCents.format = "00"
let c = (amount * 100 as NSDecimalNumber).intValue % 100
let cents = fCents.string(from: NSNumber(value: c))!
let d = (amount as NSDecimalNumber).intValue
print(d, c, amount)
let dollars = fDollars.string(from: NSNumber(value: d))!.capitalized
let s = "\(dollars) and \(cents)/100"
return s
}
print(spellDollars(1019123.08))
结果:
-825551 -32 1019123.0799999997952 负八十五二十五万五十一和-32/100
答案 0 :(得分:3)
最重要的是,问题在于您使用spellDollars
调用了Double
,并将其转换为Decimal
。您可以这样做:
print(spellDollars(Decimal(string: "1019123.08")!))
或
print(spellDollars(Decimal(sign: .plus, exponent: -2, significand: 101912308)))
这两个方法都可以在不将Double
引入Decimal
转换噪声的情况下工作。
考虑一个简化的示例:
let decimal1 = Decimal(floatLiteral: 1019123.08)
let decimal2 = Decimal(string: "1019123.08")!
let decimal3 = Decimal(sign: .plus, exponent: -2, significand: 101912308)
for value in [decimal1, decimal2, decimal3] {
print(value)
}
这将输出:
1019123.0799999997952
1019123.08
1019123.08
要了解为什么第一个示例中的Double
会转换为Decimal
的{{1}}值,建议您参考What Every Computer Scientist Should Know About Floating-Point Arithmetic。
关于为什么您从1019123.0799999997952
得到-825551的原因,我想这是由于有效位数(10191230799999997952)太大导致无法以整数格式或类似形式表示而导致的一些溢出那。
我建议您切开Gordian结,而不要使用intValue
算术来手动舍入值。使用NSDecimalRound
函数,例如
NSDecimalNumber