Округление NSDecimalNumber - PullRequest
       15

Округление NSDecimalNumber

22 голосов
/ 20 октября 2010

Мне сложнее всего разобраться в том, что, кажется, должно быть очень простым. Мне нужно точно округлить NSDecimalNumber до определенного количества десятичных разрядов (определяется во время выполнения). Насколько я могу судить, у меня есть два варианта, ни один из которых мне не нравится.

  1. Конвертировать в число с плавающей точкой и использовать функции округления C: Мне это не нравится, потому что в данном случае важна точность. Число с плавающей точкой не всегда может точно представлять десятичные числа, и это может вызвать проблемы.
  2. Преобразовать в строку, используя NSNumberFormatter, а затем преобразовать обратно: Мне не нравится этот, потому что он кажется просто уродливым и неэффективным.

Есть ли другой способ, который я пропустил? У есть простой способ округлить NSDecimalNumbers, но я не могу понять, что это за жизнь.

Ответы [ 4 ]

32 голосов
/ 21 октября 2010

Вы просто звоните decimalNumberByRoundingAccordingToBehavior: с желаемым NSDecimalNumberBehaviors протоколом. См. Ссылку NSDecimalNumberBehaviors в документах разработчика .

Обновление: см. http://www.cimgf.com/2008/04/23/cocoa-tutorial-dont-be-lazy-with-nsdecimalnumber-like-me/

19 голосов
/ 29 ноября 2015

Для тех, кто предпочитает пример кода ...

округлить до 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];

Округлить до тысячи (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];
8 голосов
/ 01 декабря 2016

Я получил его, используя приведенный ниже код в 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)

Обратите внимание на параметр масштаба, который используется для определения необходимых десятичных разрядов.Обрисовано здесь: https://developer.apple.com/reference/foundation/nsdecimalnumberhandler/1578295-decimalnumberhandlerwithrounding

0 голосов
/ 02 февраля 2017

Я использую это решение:

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
...