NSDecimalNumber问题

时间:2015-02-17 19:33:16

标签: ios swift nsdecimalnumber

在我的iOS swift应用程序中,我从网上收到一些json,其中包含一些代表货币的双值。它看起来像这样:

[{"Amount": 5.0},{"Amount":-26.07},{"Amount": 4}, ...etc]

我将这些转换为Doubles,然后尝试将这些值作为Swift“Double”提供给NSDecimalNumber的构造函数,如下所示:

let amount = NSDecimalNumber(double: amountAsDouble)

我遇到了这种方法的问题,因为我创建的NSDecimalNumber经常包含一个不同的数字,通过小数点16位。

let amount = NSDecimalNumber(double: -15.97)
println(amount)

返回-15.970000000000004096

我不想要这个,我想要-15.97。 谢谢,

5 个答案:

答案 0 :(得分:1)

我最近为自己做了这件事。我最终使用NSNumberFormatter来获得正确的小数位。

let currFormatter = NSNumberFormatter()
    currFormatter.numberStyle = .DecimalStyle
    currFormatter.roundingIncrement = 0.01
    currFormatter.minimumFractionDigits = 2
    currFormatter.maximumFractionDigits = 2

let doubleAmount = currFormatter.numberFromString(amountAsDouble) as NSNumber!
let amount = doubleAmount as Double
println(amount)

答案 1 :(得分:1)

这里有一个提示:如果您使用NSJSONSerializer,带小数点的数字实际上会转换为NSDecimalNumber。 NSDecimalNumber是NSNumber的子类。那么你在做什么:你有一个非常好的NSDecimalNumber,将值四舍五入到双倍,并尝试将双重转回NSDecimalNumber。只要检查一下你的确是一个NSDecimalNumber,如果是的话就不进行转换。

答案 2 :(得分:0)

这是因为中间双重表示导致问题。

您应该将字典中的值作为NSString个对象,并使用+ decimalNumberWithString:方法进行转换而不会丢失精度。在swift:

let amount = NSDecimalNumber(string: amountAsString)

答案 3 :(得分:0)

Double以18位十进制数字存储,您无法做任何事情,它是如何运作的。

请在此处阅读:http://en.wikipedia.org/wiki/Double-precision_floating-point_format

但是,在屏幕上显示值时,您可以像这样使用NSNumberFormatter

let amountInDouble: Double = -15.970000000000004096

let formatter = NSNumberFormatter()
formatter.numberStyle = .DecimalStyle
formatter.roundingIncrement = 0.01
formatter.maximumFractionDigits = 2

let amountAsString = formatter.stringFromNumber(NSNumber(double: amountInDouble))

if let amountAsString = amountAsString {
    println(amountAsString) // -15.97
}

答案 4 :(得分:-1)

     let amount = NSDecimalNumber.init(value: -15.97)

    let roundValue = amount.rounding(accordingToBehavior: NSDecimalNumberHandler(roundingMode: .bankers, scale: 2, raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: false))

    print(roundValue)