有没有一种简单的方法可以使用标准的Cocoa库进行分层硬币舍入?

时间:2016-05-24 19:28:44

标签: cocoa-touch internationalization nsdecimalnumber

In 2012, Canada abolished the 1¢ penny。为了允许以5美分的分辨率处理现金交易,实施了以下四舍五入政策:

  

购买时的商品及服务税(GST)或统一销售税(HST)的计算,无论是现金交易还是非现金交易,将继续计算到一分钱并加到价格中。只有交易的现金支付总额才会四舍五入。

来自Royal Canadian Mint

也就是说,所有的计算都应该尽可能准确地进行,并最终使用标准的“round half-up打破平局来达到百分之一的分辨率,但是到了现在付款的时候,进一步四舍五入到最近的镍是必需的。

对于国际化,我需要实现这一点。我还想在其他地方重复使用它,比如最终成本四舍五入到10¢,25¢等。如何使用NSDecimalNumber在iOS中完成此行为?

如果在Obj-C上这样工作,我会很高兴:

finalCost = [total roundWithResolution:@0.05];

或者在Swift中:

finalCost = total.roundWithResolution(0.05);

为了消除上面的任何歧义,这是之后的行为已经使用“round half-up”打破平局已经四舍五入到百分位:

  • $ 0.98至$ 1.02→$ 1.00
  • $ 1.03至$ 1.07→$ 1.05
  • $ 1.08至$ 1.10→$ 1.10
  • 等等

10¢

  • $ 0.96至$ 1.05→$ 1.00
  • $ 1.06至$ 1.15→$ 1.10
  • 等等

25¢

  • $ 0.88至$ 1.12→$ 1.00
  • $ 1.13至$ 1.37→$ 1.25
  • $ 1.38至$ 1.62→$ 1.50
  • $ 1.63至$ 1.87→$ 1.75
  • $ 1.88至$ 2.12→$ 2.00
  • 等等

1 个答案:

答案 0 :(得分:0)

我花了一个晚上值得四处询问并测试解决方案,但我终于想出了这个:

@implementation NSDecimalNumber (RoundWithResolution)

- (NSDecimalNumber *)roundWithResolution:(NSDecimalNumber *)resolution
{
    NSDecimalNumber *step1 = [self decimalNumberByDividingBy:resolution];
    NSDecimalNumber *step2 = [step1 round:0];
    NSDecimalNumber *step3 = [step2 decimalNumberByMultiplyingBy:resolution];
    NSDecimalNumber *step4 = [step3 round:2];
    return step4;
}

- (NSDecimalNumber *)round:(NSUInteger)decimalPlaces
{
    NSNumberFormatter *formatter = [NSNumberFormatter new];
    formatter.roundingMode = NSNumberFormatterRoundHalfUp;
    formatter.numberStyle = NSNumberFormatterNoStyle;
    formatter.maximumFractionDigits = decimalPlaces;
    return [NSDecimalNumber decimalNumberWithString:[formatter stringFromNumber:self]];
}

@end

这是基于kccu,Milo Brandt和Eric Towers的this formula on Math.SE

  

f(n,m)=floor((n/m)+0.5)*m