2

Using Swift3 and still getting the hang of things. I'm using the Decimal type because it involves currency and I'm having a difficult time with getting the rounding to work. I've read through the NSDecimalNumberHandler documentation and the rounding function but don't quite understand how to get this to work. Essentially I just want all my Decimal types in this class to round to the hundredths spot when the calculation functions I've built run.

Can someone give me quick example of how to do this? Thanks!

aUserHimself
  • 1,589
  • 2
  • 17
  • 26
Grimes47
  • 31
  • 4

3 Answers3

0

Please check this :

This is using NSDecimalNumber & NSDecimalNumberHandler :

let decimalStr = NSDecimalNumber(string: "500.2595")
let decimalStrHandler = NSDecimalNumberHandler(roundingMode: .plain, scale: 3, raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: false)
let roundedVal = decimalStr.rounding(accordingToBehavior: decimalStrHandler)
print(roundedVal) // prints 500.26

This is using NumberFormatter & Decimal :

extension Decimal {
    func roundDecimal() -> String {
        let formatter = NumberFormatter()
        formatter.minimumFractionDigits = 2
        return formatter.string(from: self as NSDecimalNumber)!
    }
}

You have to call like below :

let decimalStr = Decimal(string: "500.2595")!
print(decimalStr.roundDecimal()) // prints 500.26

let decimalFloat = Decimal(floatLiteral: 500.2595)
print(decimalFloat.roundDecimal())  // prints 500.26
Vini App
  • 7,339
  • 2
  • 26
  • 43
  • This looks like it would return a string. I'm wanting to return the value of the variable as a Decimal rounded to the hundredths spot (using the .plain rounding style in NSDecimalNumber.RoundingMode.) – Grimes47 Sep 07 '17 at 03:27
  • Updated the answer. Please check – Vini App Sep 07 '17 at 03:42
  • Vini App, thanks so much. I used the extension method and it worked. Really appreciate it. I know Decimal is a struct rather than a class and from what I read it was introduced in Swift 3. I like Decimal but wish I didn't have to cast every time I want to use NSDecimalNumber methods. – Grimes47 Sep 07 '17 at 04:27
  • ```let decimalFloat = Decimal(floatLiteral: 500.2595)``` is not accurate. ```let decimalFloat = NSNumber(floatLiteral: 500.2595).decimalValue``` gives a more accurate value. You can quickly check it in a Playground. – zeeshan May 18 '20 at 09:48
-1

You should never save a currency value as decimal number. Always use integer, like this:

1.00$ = 100
4567.89$ = 456789

And then when you want to present it not in cents you can divide by 100.

See this: Why not use Double or Float to represent currency?

Lukas
  • 169
  • 1
  • 3
  • 8
  • I'm not using a Double/Float, I'm using the Decimal struct (https://developer.apple.com/documentation/foundation/decimal). I know Float/Doubles can't exactly store decimals but my understanding is that Decimal would work for what I need. – Grimes47 Sep 06 '17 at 17:38
  • `Decimal` is a type especially created to store currency because it uses decadic, high precision arithmetics. – Sulthan Sep 06 '17 at 22:20
  • Oh ok, sorry seems that I didn't read the question well enough. – Lukas Sep 07 '17 at 06:55
-1

There is a specific function called NSDecimalRound which you can use for this. Here is an extension to Decimal which you can use to get standard round and rounded functions:

extension Decimal {
    mutating func round(_ scale: Int, _ roundingMode: NSDecimalNumber.RoundingMode) {
        var localCopy = self
        NSDecimalRound(&self, &localCopy, scale, roundingMode)
    }

    func rounded(_ scale: Int, _ roundingMode: NSDecimalNumber.RoundingMode) -> Decimal {
        var result = Decimal()
        var localCopy = self
        NSDecimalRound(&result, &localCopy, scale, roundingMode)
        return result
    }
}
Linus Unnebäck
  • 23,234
  • 15
  • 74
  • 89