舍入 NSDecimalNumber
Posted
技术标签:
【中文标题】舍入 NSDecimalNumber【英文标题】:Rounding NSDecimalNumber 【发布时间】:2010-10-20 18:46:30 【问题描述】:我很难弄清楚看起来应该很简单的东西。我需要将 NSDecimalNumber 精确地四舍五入到特定的小数位数(在运行时确定)。据我所知,我有两个选项,我都不喜欢。
-
转换为浮点数,并使用 C 舍入函数:我不喜欢这样,因为在这种情况下准确性很重要。浮点数不能总是准确地表示十进制数,这可能会导致问题。
使用 NSNumberFormatter 转换为字符串,然后再转换回来:我不喜欢这个,因为它看起来丑陋且效率低下。
还有其他我错过的方法吗? 得到有一种简单的方法可以对 NSDecimalNumbers 进行四舍五入,但我似乎无法终生弄清楚它是什么。
【问题讨论】:
【参考方案1】:您只需使用所需的NSDecimalNumberBehaviors
协议调用decimalNumberByRoundingAccordingToBehavior:
。请参阅dev docs 中的NSDecimalNumberBehaviors
参考。
更新:见http://www.cimgf.com/2008/04/23/cocoa-tutorial-dont-be-lazy-with-nsdecimalnumber-like-me/
【讨论】:
RTFM 不是响应。响应是“您只需调用 decimalNumberByRoundingAccordingToBehavior:使用所需的 NSDecimalNumberBehaviors 协议。”参考开发文档以提供各种协议的枚举,而不是在此处复制它们。【参考方案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)
注意 scale 参数,用于定义您需要的小数位。此处概述:https://developer.apple.com/reference/foundation/nsdecimalnumberhandler/1578295-decimalnumberhandlerwithrounding
【讨论】:
【参考方案4】:我正在使用这个解决方案:
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
【讨论】:
以上是关于舍入 NSDecimalNumber的主要内容,如果未能解决你的问题,请参考以下文章