This is the 22nd day of my participation in the August Wen Challenge.More challenges in August
preface
In our development projects, we more or less always do calculations in terms of money, and there are precision issues if you use Double or Float, so Apple provides an API called NSDecimalNumber, which we’ll use for you
1、 NSDecimalNumber
NSDecimalNumber is an exact calculation to solve the problem:
1, string to float and other imprecise problems. 2, accurate calculation 3, reserving decimals 4, rounding and other reserving decimals rulesCopy the code
2. Use NSDecimalNumber
String
turnNSDecimalNumber
Let decimalNumber = NSDecimalNumber(string: "0.123")Copy the code
- addition
Let decimalNumber1 = NSDecimalNumber(string: "321.321") Let decimalNumber2 = NSDecimalNumber(string: "123.123") let sum = decimalNumber1. Adding (decimalNumber2) debugPrint(sum) 444.444Copy the code
- Subtraction calculation
Let decimalNumber1 = NSDecimalNumber(string: "321.321") Let decimalNumber2 = NSDecimalNumber(string: "123.123") let subtracting = decimalNumber1. Subtracting (decimalNumber2) debugPrint (subtracting) output: 198.198Copy the code
- The multiplication calculation
Let decimalNumber1 = NSDecimalNumber(string: "321.321") Let decimalNumber2 = NSDecimalNumber(string: "123.123") let multiplying = decimalNumber1. Multiplying (by: decimalNumber2) debugPrint (multiplying) output: 39562.005483Copy the code
- Division calculation
Let decimalNumber1 = NSDecimalNumber(string: "321.321") Let decimalNumber2 = NSDecimalNumber(string: "123.123") Let dividing = decimalNumber1. DecimalNumber2) debugPrint (dividing) output: 2.60975609756097560975609756097560975609Copy the code
- It’s a little bit troublesome to write it like this every time, so let’s give
NSDecimalNumber
Add four extensions+
,-
,*
,/
public extension NSDecimalNumber {
static func + (lhs: NSDecimalNumber, rhs: NSDecimalNumber) -> NSDecimalNumber {
return lhs.adding(rhs)
}
static func - (lhs: NSDecimalNumber, rhs: NSDecimalNumber) -> NSDecimalNumber {
return lhs.subtracting(rhs)
}
static func * (lhs: NSDecimalNumber, rhs: NSDecimalNumber) -> NSDecimalNumber {
return lhs.multiplying(by: rhs)
}
static func / (lhs: NSDecimalNumber, rhs: NSDecimalNumber) -> NSDecimalNumber {
return lhs.dividing(by: rhs)
}
}
Copy the code
Use +, -, *, / directly
let sum = decimalNumber1 + decimalNumber2
let subtracting = decimalNumber1 - decimalNumber2
let multiplying = decimalNumber1 * decimalNumber2
let dividing = decimalNumber1 / decimalNumber2
Copy the code
- What if we want to keep a few decimal places? We can use
NSDecimalNumberHandler
The following is the initialization method
public init(roundingMode: NSDecimalNumber.RoundingMode, scale: Int16, raiseOnExactness exact: Bool, raiseOnOverflow overflow: Bool, raiseOnUnderflow underflow: Bool, raiseOnDivideByZero divideByZero: Bool)
Copy the code
We can see that there is a RoundingMode enumeration
public enum RoundingMode : UInt {
case plain = 0
case down = 1
case up = 2
case bankers = 3
}
Copy the code
Four of the values roughly mean:
Plain: the next digit is rounded down: the next digit is rounded down: the next digit is rounded up: the next digit is rounded up: the next digit is rounded up: the next digit is rounded up: the next digit is rounded up: the next digit is rounded up: the next digit is rounded up: the next digit is rounded up by the next bankers: When the next digit of the reserved digit is not 5, the digits are rounded. When the next digit of the reserved digit is 5, the digits preceding the reserved digit are directly rounded. If the digits are odd, the digits are directly rounded.Copy the code
Let’s try using our first plain, with two decimal places reserved, where scale is accurate to a few decimal places
Let decimalNumber1 = NSDecimalNumber(string: "321.321") Let decimalNumber2 = NSDecimalNumber(string: "123.123") let sum = decimalNumber1. Adding (decimalNumber2) let behavior = NSDecimalNumberHandler(roundingMode: .plain, scale: Int16(2), raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: True) debugPrint(product.stringValue) 444.44Copy the code
- Next to the
NSDecimalNumber
Extend a turnString
The method of
Public extension NSDecimalNumber {/// -parameter scale: keep some decimals /// -parameter roundingMode: Bankers: bankers: bankers: bankers: bankers: bankers: bankers: bankers: bankers: bankers: bankers: bankers: bankers: bankers: bankers: bankers: bankers: bankers: bankers: bankers: bankers: bankers: bankers: bankers: bankers: bankers: bankers: bankers: bankers: bankers: bankers RoundingMode: func toString(_ scale: Int = 2, roundingMode: func toString(_ scale: Int = 2, roundingMode: roundingMode: func toString(_ scale: Int = 2, roundingMode: roundingMode: RoundingMode = .plain) -> String { let behavior = NSDecimalNumberHandler( roundingMode: roundingMode, scale: Int16(scale), raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: true) let product = multiplying(by: .one, withBehavior: behavior) return product.stringValue } }Copy the code