gpt4 book ai didi

swift - NSNumber/NSDecimalNumber 奇怪的行为

转载 作者:搜寻专家 更新时间:2023-11-01 06:26:00 27 4
gpt4 key购买 nike

对于我刚好选择的测试用例,以下代码会产生奇怪的结果。来自 playground 的代码,然后是结果

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

最佳答案

归根结底,问题在于您使用 Double 调用了 spellDollars,它转换为 Decimal。你可以这样做:

print(spellDollars(Decimal(string: "1019123.08")!))

或者

print(spellDollars(Decimal(sign: .plus, exponent: -2, significand: 101912308)))

如果不引入此 DoubleDecimal 转换噪声,这两种方法都可以工作。


考虑一个简化的例子:

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 会转换为 1019123.0799999997952Decimal 值,我建议您引用 What Every Computer Scientist Should Know About Floating-Point Arithmetic .


关于您从 intValue 得到 -825551 的原因,我猜这是由于有效数 (10191230799999997952) 太大而无法以整数格式表示而导致的溢出或类似的东西。

我建议快刀斩乱麻,不要使用 NSDecimalNumber 算法来手动舍入值。使用 NSDecimalRound 函数,例如

func spellDollars(_ amount: Decimal) -> String {
// instantiate formatters

let dollarsFormatter = NumberFormatter()
dollarsFormatter.numberStyle = .spellOut
let centsFormatter = NumberFormatter()
centsFormatter.minimumIntegerDigits = 2

// get dollars

var inputAmount = amount
var dollars = Decimal.zero
NSDecimalRound(&dollars, &inputAmount, 0, .down)

// get dollars and cents

var dollarsAndCents = Decimal.zero
NSDecimalRound(&dollarsAndCents, &inputAmount, 2, .plain)

// get cents

let cents = (dollarsAndCents - dollars) * 100

// build strings

let centsString = centsFormatter.string(for: cents)!
let dollarsString = dollarsFormatter.string(for: dollars)!.capitalized
return "\(dollarsString) and \(centsString)/100"
}

关于swift - NSNumber/NSDecimalNumber 奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54621140/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com