由于 Int、Float、Double、CGFloat 都有相应的数值范围或精度限制,所以遇到较大数值计算时,可能导致计算结果数值溢出、精度丢失;使用 ‘NSDecimalNumber’ 可以避免出现上述情况
NSDecimalNumber 文档中的定义
An object for representing and performing arithmetic on base-10 numbers that bridges to Decimal; use NSDecimalNumber when you need reference semantics or other Foundation-specific behavior.
使用实例
swift 比较侧重面向协议,可以通过协议扩展 Int
、Float
、Double
、CGFloat
、String
的 NSDecimalNumber
计算方法
-
声明协议
public protocol DecimalCalculation { // 加 func decimalAdd(number: Self) -> String // 减 func decimalSubtracting(number: Self) -> String // 乘 func decimalMultiplying(number: Self) -> String // 除 func decimalDividing(number: Self) -> String }
-
实现协议的方法
public extension DecimalCalculation { // 加 func decimalAdd(number: Self) -> String { return decimalCalculate(type: .add, number: number) } // 减 func decimalSubtracting(number: Self) -> String { return decimalCalculate(type: .subtracting, number: number) } // 乘 func decimalMultiplying(number: Self) -> String { return decimalCalculate(type: .multiplying, number: number) } // 除 func decimalDividing(number: Self) -> String { return decimalCalculate(type: .dividing, number: number) } private func decimalCalculate(type: DecimalCalculateType, number: Self) -> String { let firstNum = "\(self)" let secondNum = "\(number)" let firstDecimalNumber = NSDecimalNumber(string: firstNum) let secondDecimalNumber = NSDecimalNumber(string: secondNum) switch type { case .add: return firstDecimalNumber.adding(secondDecimalNumber).stringValue case .subtracting: return firstDecimalNumber.subtracting(secondDecimalNumber).stringValue case .multiplying: return firstDecimalNumber.multiplying(by: secondDecimalNumber).stringValue case .dividing: if secondDecimalNumber.isEqual(to: NSNumber(0)) { return "被除数不能为0" } return firstDecimalNumber.dividing(by: secondDecimalNumber).stringValue } } }
-
遵守协议
extension String: DecimalCalculation {} extension CGFloat: DecimalCalculation {} extension Double: DecimalCalculation {} extension Float: DecimalCalculation {} extension Int: DecimalCalculation {}
-
For Example
// Float 的有效数字只有 6 ~ 7 位 let p1: Float = 834567.8 let p2: Float = 967889.5 let add = p1.decimalAdd(number: p2) let subtracting = p1.decimalSubtracting(number: p2) let multiplying = p1.decimalMultiplying(number: p2) let dividing = p1.decimalDividing(number: p2) print("p1 = \(p1)") print("p2 = \(p2)") print("add = \(add)") print("subtracting = \(subtracting)") print("multiplying = \(multiplying)") print("dividing = \(dividing)")
计算结果:
p1 = 834567.8 p2 = 967889.5 add = 1802457.3 subtracting = -133321.7 multiplying = 807769410658.1 dividing = 0.86225524711240281044478734400982756812