Rounding NSDecimalNumber

旧时模样 提交于 2019-12-17 19:11:04

问题


I'm having the hardest time figuring out something that seems like it should be very simple. I need to accurately round an NSDecimalNumber to a particular number of decimal places (determined at runtime.) So far as I can tell, I have two options, neither of which I like.

  1. Convert to a float, and use C rounding functions: I don't like this because accuracy matters in this case. Floats can't always accurately represent decimal numbers, and this could cause problems.
  2. Convert to a string using NSNumberFormatter and then convert back: I don't like this one because it just seems ugly and inefficient.

Is there another way that I've missed? There has got to be an easy way to do rounding of NSDecimalNumbers, but I can't seem to figure out for the life of me what it is.


回答1:


You simply call decimalNumberByRoundingAccordingToBehavior:with the desired NSDecimalNumberBehaviors protocol. See the NSDecimalNumberBehaviors reference in the dev docs.

Update: See http://www.cimgf.com/2008/04/23/cocoa-tutorial-dont-be-lazy-with-nsdecimalnumber-like-me/




回答2:


For those that prefer example code...

To round to 2 decimal places (12345.68):

NSDecimalNumber *originalNumber = [NSDecimalNumber decimalNumberWithString:@"12345.6789"];
NSDecimalNumberHandler *behavior = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundPlain
                                                                                          scale:2
                                                                               raiseOnExactness:NO
                                                                                raiseOnOverflow:NO
                                                                               raiseOnUnderflow:NO
                                                                            raiseOnDivideByZero:NO];

NSDecimalNumber *roundedNumber = [originalNumber decimalNumberByRoundingAccordingToBehavior:behavior];

To round to the nearest thousand (12000):

NSDecimalNumber *originalNumber = [NSDecimalNumber decimalNumberWithString:@"12345.6789"];
NSDecimalNumberHandler *behavior = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundPlain
                                                                                          scale:-3
                                                                               raiseOnExactness:NO
                                                                                raiseOnOverflow:NO
                                                                               raiseOnUnderflow:NO
                                                                            raiseOnDivideByZero:NO];

NSDecimalNumber *roundedNumber = [originalNumber decimalNumberByRoundingAccordingToBehavior:behavior];



回答3:


I got it working using the below code in Swift 3.

let amount = NSDecimalNumber(string: "123.456789")
let handler = NSDecimalNumberHandler(roundingMode: .plain, scale: 2, raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: false)
let roundedAmount = amount.rounding(accordingToBehavior: handler)

Note the scale parameter, used to define the decimal places you need. Outlined here: https://developer.apple.com/reference/foundation/nsdecimalnumberhandler/1578295-decimalnumberhandlerwithrounding




回答4:


I'm using this solution:

import Foundation

extension NSDecimalNumber {
    public func round(_ decimals:Int) -> NSDecimalNumber {
        return self.rounding(accordingToBehavior:
            NSDecimalNumberHandler(roundingMode: .plain,
                                   scale: Int16(decimals),
                                   raiseOnExactness: false,
                                   raiseOnOverflow: false,
                                   raiseOnUnderflow: false,
                                   raiseOnDivideByZero: false))
    }
}

let amount = NSDecimalNumber(string: "123.456")

amount.round(2)  --> 123.46
amount.round(1)  --> 123.5
amount.round(0)  --> 123
amount.round(-1) --> 120
amount.round(-2) --> 100


来源:https://stackoverflow.com/questions/3981219/rounding-nsdecimalnumber

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!