简体   繁体   English

舍入NSDecimalNumber

[英]Rounding NSDecimalNumber

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. 我需要准确地将NSDecimalNumber舍入到特定数量的小数位(在运行时确定)。据我所知,我有两个选项,我都不喜欢。

  1. Convert to a float, and use C rounding functions: I don't like this because accuracy matters in this case. 转换为浮点数,并使用C舍入函数:我不喜欢这样,因为在这种情况下准确性很重要。 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. 使用NSNumberFormatter转换为字符串然后转换回来:我不喜欢这个,因为它看起来很丑陋而效率低下。

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. 必须一个简单的方法来完成NSDecimalNumbers的舍入,但我似乎无法弄清楚它的生命是什么。

You simply call decimalNumberByRoundingAccordingToBehavior: with the desired NSDecimalNumberBehaviors protocol. 您只需使用所需的NSDecimalNumberBehaviors协议调用decimalNumberByRoundingAccordingToBehavior: . See the NSDecimalNumberBehaviors reference in the dev docs . 请参阅开发文档中NSDecimalNumberBehaviors参考。

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

For those that prefer example code... 对于那些喜欢示例代码的人......

To round to 2 decimal places (12345.68): 要舍入到2位小数(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): 要舍入到最接近的千位(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];

I got it working using the below code in Swift 3. 我使用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. 请注意scale参数,用于定义所需的小数位数。 Outlined here: https://developer.apple.com/reference/foundation/nsdecimalnumberhandler/1578295-decimalnumberhandlerwithrounding 在此概述: https//developer.apple.com/reference/foundation/nsdecimalnumberhandler/1578295-decimalnumberhandlerwithrounding

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

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

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