Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift NumberFormatter formatting all values to 3 decimal places?



I have a large array of doubles, which have a varying number of decimal places, such as:

[11307.3, 1025.64, 1.27826, 1676.46, 0.584175, 183.792, 1.02237, 13.649, 0.472665, 127.604]

I am attempting to format the number so there are commas every thousand and the decimal places are not formatted to a specific number such as 3dp. The array should look like

[11,307.3, 1,025.64, 1.27826, 1,676.46, 0.584175, 183.792, 1.02237, 13.649, 0.472665, 127.604]


I have tried doing this by defining NumberFormatter as such:

let numberFormatter = NumberFormatter()

and then choosing decimal for style:

numberFormatter.numberStyle = NumberFormatter.Style.decimal

The values in the array are display in a table view, and when a user taps on for example the 2nd cell, in a new screen the value 1,025.64 would be displayed. I used this code to do that:

var formattedPrice = numberFormatter.string(from: NSNumber(value:coinPriceDouble!))
self.coinPriceLbl.text = "\(coinTitleText!): \(Cryptocoin.instance.fiatSymbol)\(formattedPrice!)"


This works perfect for any value that does not have more than 3 decimal places. If the user chose the 3rd value in the array, it would display 1.278 not 1.27826.

Is there any way to format these values with commas but not force them to a specific number of decimal places?

like image 600
Jeremy Avatar asked Nov 28 '22 13:11

Jeremy


2 Answers

As vadian said, NumberFormatter is highly customisable.

Just play around its properties, like (you need to customise based on your needs):

let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .decimal
numberFormatter.maximumFractionDigits = 3

Here the explanation for NumberFormatter's maximumFractionDigits property and related.

Here instead a blog that explains all the related aspects of NumberFormatter A Guide to NSNumberFormatter.

EDIT

Put the following code in a Playground and observe the result:

let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .decimal
numberFormatter.maximumFractionDigits = 3

let formattedNumbers = [11307.3, 1025.64, 1.27826, 1676.46, 0.584175, 183.792, 1.02237, 13.649, 0.472665, 127.604].flatMap { number in
    return numberFormatter.string(from: number)
}
print(formattedNumbers)
like image 163
Lorenzo B Avatar answered Dec 28 '22 09:12

Lorenzo B


Link: https://stackoverflow.com/a/27571946/6655075 .

This solved my problem. As I had 3 values displaying, each from a different array, I would end up formatting all 3 whereas I only wanted to format 1 array.

   extension Double {
        static let twoFractionDigits: NumberFormatter = {
            let formatter = NumberFormatter()
            formatter.numberStyle = .decimal
            formatter.minimumFractionDigits = 2
            formatter.maximumFractionDigits = 2
            return formatter
        }()
        var formatted: String {
            return Double.twoFractionDigits.string(for: self) ?? ""
        }
    }

I removed

var formattedPrice = numberFormatter.string(from: NSNumber(value:coinPriceDouble!))    


And simply used

self.coinPriceLbl.text = "\(coinTitleText!): \(Cryptocoin.instance.fiatSymbol)\(coinPriceDouble!.formatted)"



Edit: As Dávid Pásztor mentioned, I only want to add the comma separator to the values which need it while still maintaining the precision of each value down to the last decimal value.

like image 36
Jeremy Avatar answered Dec 28 '22 09:12

Jeremy