问题描述
我在iPhone应用程序中看到一些奇怪的错误,我已经缩小到使用NSNumberFormatter。
I'm seeing some strange bugs in my iPhone app that I have narrowed down to my use of NSNumberFormatter.
一个精简的例子...
A stripped down example...
在Xcode游乐场我有:
In Xcode playground I have:
let numberFormatter = NSNumberFormatter()
//numberFormatter.numberStyle = .DecimalStyle - does not change behavior
let numberString = "546000.06"
let number: NSNumber = numberFormatter.numberFromString(numberString)!
print("number: \(number)")
let number1: NSNumber = NSDecimalNumber(string: numberString)
print("number1: \(number1)")
这是输出:
number: 546000.0600000001
number1: 546000.06
请注意,将numberStyle设置为.DecimalStyle不会改变任何内容。
Note that setting the numberStyle to .DecimalStyle doesn't change anything.
此问题仅发生在某些数值上(例如,8.03是另一个一)。我认为NSNumberFormatter对于这种类型的转换是安全的,我没有在互联网上看到很多关于这个问题的噪音,所以我想假设它是我做错了。
This issue only happens for certain numeric values (for example, 8.03 is another one). I thought NSNumberFormatter was safe for this type of conversion and I haven't seen much noise about this issue on the internet so I want to assume it is something I am doing wrong.
任何人都可以解释我所看到的内容吗?非常感谢任何帮助!
Can anyone explain what I am seeing? Any help is very much appreciated!
推荐答案
看起来NSNumberFormatter存在问题。有一些值可以使这个舍入误差逐渐增加。在XCode 7.2.1游乐场中,它显示大约8.03。
It looks like there is an issue with NSNumberFormatter. There are certain values where this rounding error creeps up. In the XCode 7.2.1 playground, it shows up around 8.03.
我解决这个问题的一种方法是舍入十进制数。由于差值为+/-很小,因此四舍五入到四分之一的位置应该有效。您可以使用各种舍入模式。在这个例子中,我使用了RoundPlain。
One way that I've solved this is to round the decimal number. Since the difference is +/- a tiny amount, rounding to 4 fraction places should work. You can use various rounding modes. In this example I used RoundPlain.
var initialValue = NSDecimalNumber(string: "7")
let handler = NSDecimalNumberHandler(roundingMode: NSRoundingMode.RoundPlain, scale: 4, raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: false)
let numberFormatter = NSNumberFormatter()
for index in 1...300 {
initialValue = initialValue.decimalNumberByAdding(0.01)
let stringValue = "\(initialValue)"
var number = numberFormatter.numberFromString(stringValue)
var decimalNumber: NSDecimalNumber = NSDecimalNumber(decimal: number!.decimalValue)
decimalNumber = decimalNumber.decimalNumberByRoundingAccordingToBehavior(handler)
print("stringValue = \(stringValue), decimalNumber = \(decimalNumber), number = \(number!)")
}
这篇关于NSNumberFormatter numberFromString在转换某些数字时会添加一小部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!