简体   繁体   English

NSDecimalNumber问题

[英]NSDecimalNumber issues

In my iOS swift application, I receive some json from the web which contains some double values which represent currency. 在我的iOS swift应用程序中,我从网络上收到一些json,其中包含一些表示货币的双精度值。 It looks like this: 看起来像这样:

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

I cast these as Doubles and then try to feed these values as a Swift "Double" into the NSDecimalNumber's constructor like this: 我将它们转换为Doubles,然后尝试将这些值作为Swift“ Double”馈入NSDecimalNumber的构造函数中,如下所示:

let amount = NSDecimalNumber(double: amountAsDouble)

I'm running into problems with this approach because very frequently the NSDecimalNumber I created will contain a different number that goes 16 places passed the decimal point. 我遇到了这种方法的问题,因为我创建的NSDecimalNumber通常会包含一个不同的数字,该数字会超过小数点后16位。

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

this returns -15.970000000000004096 这将返回-15.970000000000004096

I don't want this, I want -15.97. 我不要,我要-15.97。 Thanks, 谢谢,

I recently went through this for myself. 我最近亲自做了这个。 I ended up using an NSNumberFormatter to get the proper decimal places. 我最终使用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)

Here's a tip: If you use NSJSONSerializer, numbers with decimal points are actually turned into NSDecimalNumber for you. 提示:如果使用NSJSONSerializer,带小数点的数字实际上会变成NSDecimalNumber。 NSDecimalNumber is a subclass of NSNumber. NSDecimalNumber是NSNumber的子类。 So what you are doing: You've got a perfectly fine NSDecimalNumber, round the value to double, and try to turn the double back into an NSDecimalNumber. 因此,您在做什么:您已经得到了一个非常好的NSDecimalNumber,将值四舍五入为double,然后尝试将double变回NSDecimalNumber。 Just check that what you have is indeed an NSDecimalNumber, and do no conversion if it is. 只需检查您所拥有的确实是NSDecimalNumber,如果是则不进行任何转换。

This is because the intermediate double representation is causing problems. 这是因为中间的双重表示引起了问题。

You should take the values from your dictionary as NSString objects and use the + decimalNumberWithString: method to convert without losing precision. 您应该将字典中的值用作NSString对象,并使用+ decimalNumberWithString:方法进行转换而不会损失精度。 In swift: 迅速:

let amount = NSDecimalNumber(string: amountAsString)

A Double is stored with 18 decimal digits, you can't do anything about that, it's how it works. Double以18位十进制数字存储,您无法执行任何操作,这就是它的工作方式。

Read here: http://en.wikipedia.org/wiki/Double-precision_floating-point_format 在这里阅读: http : //en.wikipedia.org/wiki/Double-precision_floating-point_format

However, at the time of displaying the value on the screen, you can use NSNumberFormatter like this: 但是,在屏幕上显示该值时,可以使用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
}
     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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM