NSDecimalNumber 使用

NSDecimalNumber是使用貨幣時最好的格式。
官方文檔

NSDecimalNumber 是 NSNumber 的一個子類, 比 NSNumber 的功能更為強大, 四舍五入, 取整, 輸入后自動去掉數(shù)值前面無用的 0 等等. 由于 NSDecimalNumber 精度較高, 所以會比基本數(shù)據(jù)類型費時, 所以需要權(quán)衡考慮, 蘋果官方建議在貨幣以及要求精度很高的場景下使用.
通常情況下我們會使用 NSDecimalNumberHandler 這個格式化器對其需要約束的格式進行設(shè)置

NSDecimalNumberHandler

 let decHandler:NSDecimalNumberHandler = NSDecimalNumberHandler.init(roundingMode: .plain, scale: 2, raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: true)

roundingMode 文檔是一個枚舉類型

 public enum RoundingMode : UInt {

        
        case plain = 0 //只入不舍

        case down = 1//只舍不入

        case up = 2//四舍五入

        case bankers = 3//四舍六入, 中間值時, 取最近的,保持保留最后一位為偶數(shù)
    }

scale: 保留幾位小數(shù)

raiseOnExactness: 發(fā)生精確錯誤時是否拋出異常,一般為false

raiseOnOverflow: 發(fā)生溢出錯誤時是否拋出異常,一般為false

raiseOnUnderflow: 發(fā)生不足錯誤時是否拋出異常,一般為false

raiseOnDivideByZero: 除數(shù)是0時是否拋出異常,一般為true

補零問題

NSDecimalNumber 做精度限制, 如果小數(shù)點后面是以0結(jié)尾, 則不會顯示,如1024.00 保留2位小數(shù) 結(jié)果為:1024
前端為了顯示效果需要補零操作

    let decNumber = NSDecimalNumber.init(string: "1024")
    let decHandler:NSDecimalNumberHandler = NSDecimalNumberHandler.init(roundingMode: .plain, scale: 2,   raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: true)
    let dNumber = decNumber.rounding(accordingToBehavior: decHandler)
    let p = 2
    let count : Int = (p < 0 ? 0 : p)
    var formatterString : String = "0."
    if count == 0 {
        formatterString = "0"
    }
    for _ in 0 ..< count {
        formatterString.append("0")
    }
    let formatter : NumberFormatter = NumberFormatter()
    formatter.positiveFormat = formatterString
    formatter.string(from: dNumber)!

完整方法

func precisionString(with number:String, precision: String , isRound: Bool = false) -> String {
  
   guard isPurnFloat(string: number) && isPurnFloat(string: precision) else {
       return number
   }
   guard conerData(precision, .MyInt).0! >= 0 else {
       return number
   }

   let decNumber = NSDecimalNumber.init(string: number)

   var decHandler:NSDecimalNumberHandler?
   if isRound {
       decHandler = NSDecimalNumberHandler.init(roundingMode: .plain, scale: Int16(precision)!, raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: true)
   }else{
       if conerData(number, .MyDouble).2! > 0 {
           decHandler = NSDecimalNumberHandler.init(roundingMode: .up, scale: Int16(precision)!, raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: true)
       }else{
           decHandler = NSDecimalNumberHandler.init(roundingMode: .up, scale: Int16(precision)!, raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: true)
       }
   }
   let dNumber = decNumber.rounding(accordingToBehavior: decHandler)
   let p = conerData(precision, .MyInt).0!
   let count : Int = (p < 0 ? 0 : p)
   var formatterString : String = "0."
   if count == 0 {
       formatterString = "0"
   }
   for _ in 0 ..< count {
       formatterString.append("0")
   }
   let formatter : NumberFormatter = NumberFormatter()
   formatter.positiveFormat = formatterString
   return formatter.string(from: dNumber)!
}
//MARK:- 是否數(shù)字
public func isPurnFloat(string: String) -> Bool {
    let scan: Scanner = Scanner(string: string)
    var val:Double = 0
    return scan.scanDouble(&val) && scan.isAtEnd
}

NSDecimalNumber運算

NSDecimalNumber:是蘋果針對浮點型計算時存在精度誤差的問題而提供的一個類

let num1 = NSDecimalNumber.init(string: "1024.1024")
let num2 = NSDecimalNumber.init(string: "1024.1024")
//加
String(format: "%@", num1.adding(num2))
//減
String(format: "%@", num1.subtracting(num2))
//乘
String(format: "%@", num1.multiplying(num2))
//除
String(format: "%@", num1.dividing(num2))
//n次方(2次方)
String(format: "%@", num1.raising(toPower: 2))
//指數(shù)
String(format: "%@", num1.multiplying(byPowerOf10: 2))

相關(guān)文檔

    open func adding(_ decimalNumber: NSDecimalNumber) -> NSDecimalNumber

    open func adding(_ decimalNumber: NSDecimalNumber, withBehavior behavior: NSDecimalNumberBehaviors?) -> NSDecimalNumber

    
    open func subtracting(_ decimalNumber: NSDecimalNumber) -> NSDecimalNumber

    open func subtracting(_ decimalNumber: NSDecimalNumber, withBehavior behavior: NSDecimalNumberBehaviors?) -> NSDecimalNumber

    
    open func multiplying(by decimalNumber: NSDecimalNumber) -> NSDecimalNumber

    open func multiplying(by decimalNumber: NSDecimalNumber, withBehavior behavior: NSDecimalNumberBehaviors?) -> NSDecimalNumber

    
    open func dividing(by decimalNumber: NSDecimalNumber) -> NSDecimalNumber

    open func dividing(by decimalNumber: NSDecimalNumber, withBehavior behavior: NSDecimalNumberBehaviors?) -> NSDecimalNumber

    
    open func raising(toPower power: Int) -> NSDecimalNumber

    open func raising(toPower power: Int, withBehavior behavior: NSDecimalNumberBehaviors?) -> NSDecimalNumber

 // compare two NSDecimalNumbers
    
    open class var defaultBehavior: NSDecimalNumberBehaviors

    // One behavior per thread - The default behavior is
    //   rounding mode: NSRoundPlain
    //   scale: No defined scale (full precision)
    //   ignore exactnessException
    //   raise on overflow, underflow and divide by zero.
    
    open var objCType: UnsafePointer<CChar> { get }

    // return 'd' for double
    
    open var doubleValue: Double { get }
    
    open func multiplying(byPowerOf10 power: Int16) -> NSDecimalNumber

    open func multiplying(byPowerOf10 power: Int16, withBehavior behavior: NSDecimalNumberBehaviors?) -> NSDecimalNumber
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • NSDecimalNumber是NSNumber的子類,比NSNumber的功能更為強大,可以指定一個數(shù)的冪,四舍...
    博爾茨杰閱讀 2,007評論 0 1
  • 后臺返回的金額數(shù)是字符串NSString,要對其進行計算的話,當時就轉(zhuǎn)成CGFloat,結(jié)果發(fā)現(xiàn)轉(zhuǎn)后的數(shù)值不準確了...
    就用帥氣點的昵稱吧閱讀 1,600評論 0 1
  • 在客戶端處理金額的時候,通常會涉及小數(shù)點后兩位有效數(shù)字,如果使用float和double的時候都會因為精度...
    獻國閱讀 2,136評論 0 1
  • 繼承NSNumber,用來處理精準計算。之前的一個電商項目中,就經(jīng)常會遇到這樣一個問題。使用自帶解析 [NSJSO...
    咚咚嗒大人閱讀 701評論 0 0
  • 場景: 我們在做金錢計算的時候會遇到一個問題,就是精確的問題,許多項目尤其是電商類項目都會涉及到,就是當我們對價格...
    被吹落的風(fēng)閱讀 1,351評論 0 0

友情鏈接更多精彩內(nèi)容