2010-10-20 20 views
20

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

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

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

ответ

32

Вы просто позвоните decimalNumberByRoundingAccordingToBehavior: с помощью нужного протокола NSDecimalNumberBehaviors. См. Ссылку NSDecimalNumberBehaviors в dev docs.

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

+0

Это билет! Благодаря! –

+0

Отличная ссылка тоже :-) – 2012-06-11 13:03:58

+0

RTFM не был ответом. Ответ был: «Вы просто вызываете decimalNumberByRoundingAccordingToBehavior: с требуемым протоколом NSDecimalNumberBehaviors». В документах dev указывалось, что они перечисляют различные протоколы, а не копируют их здесь. – CuriousRabbit

17

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

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

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

0

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

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 
Смежные вопросы