Swift how to format a large number with thousands separators? - swift

Is there a simple command to format 1.60543e+06 to 1,605,436???
resultFV.text = String.localizedStringWithFormat("%f", fv)
does not get it.

In Swift 3,
NumberFormatter.localizedString(from: NSNumber(value: whatever), number: NumberFormatter.Style.decimal)

Swift Xcode 6.3, SOLVED (I decided to leave the $ in the code). If you don't want a $ in the output, change .CurrencyStyle to .DecimalStyle
var fv = 3534234.55
var formatter = NSNumberFormatter()
formatter.numberStyle = .CurrencyStyle
formatter.maximumFractionDigits = 0;
resultFV.text = formatter.stringFromNumber(fv) // result: $3,534,235 –

You should use a NumberFormatter for that:
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .decimal
resultFV.text = numberFormatter.string(from: fv)

Update for Swift 4.1 currency string:
let balance = 1234567
let formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.maximumFractionDigits = 0
let result = formatter.string(from: NSNumber(value: balance))
// result: $1,234,567
You can change formatter.numberStyle to .decimal to leave it as number without "$" sign.

You can achieve this by using String initializers in Swift 3+:
// 1605436
let value: Int = 1605436
// "1,605,436" where Locale == en_US
let formattedInt = String(format: "%d", locale: Locale.current, value)
// "1,605,436" where Locale == en_US
let formattedDouble = String(format: "%.0f", locale: Locale.current, Double(value))

Update for Swift 5
var unformattedValue : Double = 3534234.55
var formatter = NumberFormatter()
formatter.numberStyle = .currency // or .decimal if desired
formatter.maximumFractionDigits = 2; //change as desired
formatter.locale = Locale.current // or = Locale(identifier: "de_DE"), more locale identifier codes: https://gist.github.com/jacobbubu/1836273
var displayValue : String = formatter.string(from: NSNumber(value: unformattedValue))! // displayValue: "$3,534,235" ```

Why don't you limit the precision, like ".0f"
resultFV.text = String.localizedStringWithFormat("%.0f", fv)
Updated Answer:
var formatter: NSNumberFormatter = NSNumberFormatter()
formatter.numberStyle = NSNumberFormatterStyle.DecimalStyle;
var formattedStr: NSString = formatter.stringFromNumber(NSNumber(double: fv))!
resultFV.text = formattedStr

Updated
Using Data Formatting available in Foundation for macOS 12.0+, iOS 15.0+, tvOS 15.0+, and watchOS 8.0+.
let number: Int = 1000
let formatted = number.formatted(.number.grouping(.never))
print(formatted)
console output: "1000"
number can be any BinaryFloatingPoint or BinaryInteger

Related

iOS Swift - Convert double to String precision last value rounded to next value

Example value : 3.00035358. i am trying to convert double value to string
Method 1:
let num = NSNumber(value:self)
let formatter : NumberFormatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.minimumFractionDigits = 4
let str = formatter.string(from: num)!
return str
method2 :
extension Double {
var stringWithoutZeroFraction: String {
return truncatingRemainder(dividingBy: 1) == 0 ? String(d: "%.0f", self) : String(format:"%.4f", self)
}
}
expecting output to be 3.003 but getting like 3.004. i do want my last digit to be rounded to next digit.how to fix tho issue.any help will be appricated.thanks in advance
If you use a NumberFormatter, you need to set the roundingMode to .floor to achieve truncating. Also, if you want to truncate, you probably want to set maximumFractionDigits instead of minimumFractionDigits.
extension Double {
var string: String {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.maximumFractionDigits = 4
formatter.roundingMode = .floor
return formatter.string(for: self) ?? description
}
}
3.00035358.string // "3.0003"

How to convert NSNumber to String in Swift4?

How to convert an Array of NSNumber to Array of String in order to display the value in UITableView?
cell.textlabel.text = ?
Code:
var a = [68.208983, 6.373902, 1.34085, 3.974012, 110.484001,
61.380001, 1.325202, 0.8501030000000001, 0.8501030000000001,
0.8501030000000001, 3.647296, 1.28503]
just add
.stringValue
to your NSNumber variable
From what you posted is an array of Double if you don't annotate them explicitly. If the array you posted is as it is, then you need this:
let arrayOfDoubles = [68.208983, 6.373902, 1.34085, 3.974012, 110.484001, 61.380001, 1.325202, 0.8501030000000001, 0.8501030000000001, 0.8501030000000001, 3.647296, 1.28503]
let stringArrayOfDoubles = arrayOfDoubles.map { String($0) }
Or, if you explicitly annotate the type as [NSNumber] then you will need this:
let arrayOfNumbers: [NSNumber] = [68.208983, 6.373902, 1.34085, 3.974012, 110.484001, 61.380001, 1.325202, 0.8501030000000001, 0.8501030000000001, 0.8501030000000001, 3.647296, 1.28503]
let stringArrayOfNumbers = arrayOfNumbers.map { $0.stringValue }
If you're going to display numeric data to the user, it's best to use a number formatter. That way your output will adapt to the formatting that your users are used to and expect based on their locale. It also allows you to configure how the numbers are presented (number of fraction digits, significant digits, rounding, etc.) without having to modify the numbers. For example, if you want to format a number as a decimal with two fraction digits, you would configure the formatter like this:
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.maximumFractionDigits = 2
Depending on the user's locale, the output (thousand separator, decimal separator, and even digits(!)) will vary:
formatter.locale = Locale(identifier: "en")
formatter.string(from: 12345.6789) // 12,345.68
formatter.string(from: 0.12345) // 0.12
formatter.locale = Locale(identifier: "sv")
formatter.string(from: 12345.6789) // 12 345,68
formatter.string(from: 0.12345) // 0,12
formatter.locale = Locale(identifier: "hi")
formatter.string(from: 12345.6789) // १२,३४५.६८
formatter.string(from: 0.12345) // ०.१२
formatter.locale = Locale(identifier: "ar")
formatter.string(from: 12345.6789) // ١٢٬٣٤٥٫٦٨
formatter.string(from: 0.12345) // ٠٫١٢
Other number styles can be used to format other types of numeric data like currency, percent, or ordinal numbers:
formatter.locale = Locale(identifier: "en")
formatter.numberStyle = .ordinal
formatter.string(from: 1) // 1st
formatter.string(from: 2) // 2nd
formatter.string(from: 3) // 3rd
formatter.string(from: 4) // 4th
Convert givent value in to String.
If given value is nil then it will return empty string.
class func toString(_ anything: Any?) -> String {
if let any = anything {
if let num = any as? NSNumber {
return num.stringValue
} else if let str = any as? String {
return str
}
}
return ""
}
Just Copy paste this method convert to string without crash issue
Thanks.

Unable to convert very small string value to decimal with NumberFormatter Swift4

I try to convert string "0.0004131955" to decimal/double/currency with NumberFormatter. It produces nil.
How to convert it?
My sample code is as below:
let formatter = NumberFormatter()
formatter.locale = Locale.current
formatter.numberStyle = .currency
formatter.minimumFractionDigits = 1
formatter.maximumFractionDigits = 15
formatter.usesGroupingSeparator = true
//number is nil here
if let number = formatter.number(from: "0.0004131955") {
let unitPrice = number.doubleValue
}
What am I doing wrong?
Remove the currency from numberStyle - copy to a playground to test
import UIKit
import PlaygroundSupport
let formatter = NumberFormatter()
formatter.locale = Locale.current
//formatter.numberStyle = .currency
formatter.minimumFractionDigits = 1
formatter.maximumFractionDigits = 15
formatter.usesGroupingSeparator = true
let number: NSNumber? = formatter.number(from: "0.0004131955")
let unitPrice: Double? = number?.doubleValue
HI #erdemgc for Number stlye Deciamal your code is working fine for me you can check console in below image
and for the currency you have to specify a currency style format you for Example i am attaching a image please take a look of below description

Add remove currency formatting in Swift

I use
func formatAmount(number:NSNumber) -> String {
let formatter = NSNumberFormatter()
formatter.numberStyle = .CurrencyStyle
return formatter.stringFromNumber(number)!
}
for changing the number to currency formatted string, but I need to remove the formatting and get just number, I need to remove the comma and currency symbol. is there any specific way? Please let me know.
I tried
func removeFormatAmount(string:String) -> NSNumber {
let formatter = NSNumberFormatter()
formatter.numberStyle = .NoStyle
formatter.currencySymbol = .None
formatter.currencyGroupingSeparator = .None
return formatter.numberFromString(string)!
}
and this gives me nil value.
UPDATE
I figured out that if text does not contain $ sign then formatting with currency will give nil value so what I did is
if string.containsString("$") {
formatter.numberStyle = .CurrencyStyle
}
return formatter.numberFromString(string)?.floatValue
now it just gives me good result.
You can create a string extension to do that
For Swift 3:
extension String {
func removeFormatAmount() -> Double {
let formatter = NumberFormatter()
formatter.locale = Locale(identifier: "en_US")
formatter.numberStyle = .currency
formatter.currencySymbol = "$"
formatter.decimalSeparator = ","
return formatter.number(from: self) as Double? ?? 0
}
}
To use:
let currencyString = "$1,000.00"
let amount = currencyString.removeFormatAmount() // 1000.0
func formatAmount(number:NSNumber) -> String{
let formatter = NSNumberFormatter()
formatter.numberStyle = .CurrencyStyle
formatter.currencySymbol = "" // <--------
formatter.currencyGroupingSeparator = "" // <--------
return formatter.stringFromNumber(number)!
}
Swift 4+
This removes currency format from all languages
extension String {
public func removeFormatAmount() -> Double {
let formatter = NumberFormatter()
formatter.locale = Locale.current
formatter.numberStyle = .currency
formatter.currencySymbol = Locale.current.currencySymbol
formatter.decimalSeparator = Locale.current.groupingSeparator
return formatter.number(from: self)?.doubleValue ?? 0.00
}
}
Example:
let currencyString = "$100.00"
let amount = currencyString.removeFormatAmount() // 100.0
NSNumberFormatter has a function numberFromString that you can use
let formatter = NSNumberFormatter()
formatter.numberStyle = .CurrencyStyle
if let number = formatter.numberFromString(string) {
//Use number
}
If you want the string from number it's easy to just build a string from that number afterwards
var number = formatter.numberFromString(string)!
var string = "\(number)"
func removeFormatAmount(string:String) -> NSNumber{
let formatter = NSNumberFormatter()
// specify a locale where the decimalSeparator is a comma
formatter.locale = NSLocale(localeIdentifier: "pt_BR")
formatter.numberStyle = .CurrencyStyle
formatter.currencySymbol = "$"
formatter.decimalSeparator = ","
return formatter.numberFromString(string) ?? 0
}
removeFormatAmount("$15,99") // 15.99

Formatting input for currency with NSNumberFormatter in Swift

I am creating a budget app that allows the user to input their budget as well as transactions. I need to allow the user to enter both pence and pounds from separate text fields and they need to be formatted together with currency symbols. I have this working fine at the moment but would like to make it localised as currently it only works with GBP. I have been struggling to convert NSNumberFormatter examples from Objective-C to Swift.
My first issue is the fact that I need to set the placeholders for the input fields to be specific to the users location. Eg. Pounds and Pence, Dollars and Cents etc...
The second issue is that the values inputted in each of the text fields such as 10216 and 32 need to be formatted and the currency symbol specific to the users location needs to be added. So it would become £10,216.32 or $10,216.32 etc...
Also, I need to use the result of the formatted number in a calculation. So how can I do this without running into issues without running into issues with the currency symbol?
Here's an example on how to use it on Swift 3.
( Edit: Works in Swift 5 too )
let price = 123.436 as NSNumber
let formatter = NumberFormatter()
formatter.numberStyle = .currency
// formatter.locale = NSLocale.currentLocale() // This is the default
// In Swift 4, this ^ was renamed to simply NSLocale.current
formatter.string(from: price) // "$123.44"
formatter.locale = Locale(identifier: "es_CL")
formatter.string(from: price) // $123"
formatter.locale = Locale(identifier: "es_ES")
formatter.string(from: price) // "123,44 €"
Here's the old example on how to use it on Swift 2.
let price = 123.436
let formatter = NSNumberFormatter()
formatter.numberStyle = .CurrencyStyle
// formatter.locale = NSLocale.currentLocale() // This is the default
formatter.stringFromNumber(price) // "$123.44"
formatter.locale = NSLocale(localeIdentifier: "es_CL")
formatter.stringFromNumber(price) // $123"
formatter.locale = NSLocale(localeIdentifier: "es_ES")
formatter.stringFromNumber(price) // "123,44 €"
Swift 3:
If you are looking for a solution that gives you:
"5" = "$5"
"5.0" = "$5"
"5.00" = "$5"
"5.5" = "$5.50"
"5.50" = "$5.50"
"5.55" = "$5.55"
"5.234234" = "5.23"
Please use the following:
func cleanDollars(_ value: String?) -> String {
guard value != nil else { return "$0.00" }
let doubleValue = Double(value!) ?? 0.0
let formatter = NumberFormatter()
formatter.currencyCode = "USD"
formatter.currencySymbol = "$"
formatter.minimumFractionDigits = (value!.contains(".00")) ? 0 : 2
formatter.maximumFractionDigits = 2
formatter.numberStyle = .currencyAccounting
return formatter.string(from: NSNumber(value: doubleValue)) ?? "$\(doubleValue)"
}
I have implemented the solution provided by #NiñoScript as an extension as well:
Extension
// Create a string with currency formatting based on the device locale
//
extension Float {
var asLocaleCurrency:String {
var formatter = NSNumberFormatter()
formatter.numberStyle = .CurrencyStyle
formatter.locale = NSLocale.currentLocale()
return formatter.stringFromNumber(self)!
}
}
Usage:
let amount = 100.07
let amountString = amount.asLocaleCurrency
print(amount.asLocaleCurrency())
// prints: "$100.07"
Swift 3
extension Float {
var asLocaleCurrency:String {
var formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.locale = Locale.current
return formatter.string(from: self)!
}
}
Xcode 11 • Swift 5.1
extension Locale {
static let br = Locale(identifier: "pt_BR")
static let us = Locale(identifier: "en_US")
static let uk = Locale(identifier: "en_GB") // ISO Locale
}
extension NumberFormatter {
convenience init(style: Style, locale: Locale = .current) {
self.init()
self.locale = locale
numberStyle = style
}
}
extension Formatter {
static let currency = NumberFormatter(style: .currency)
static let currencyUS = NumberFormatter(style: .currency, locale: .us)
static let currencyBR = NumberFormatter(style: .currency, locale: .br)
}
extension Numeric {
var currency: String { Formatter.currency.string(for: self) ?? "" }
var currencyUS: String { Formatter.currencyUS.string(for: self) ?? "" }
var currencyBR: String { Formatter.currencyBR.string(for: self) ?? "" }
}
let price = 1.99
print(Formatter.currency.locale) // "en_US (current)\n"
print(price.currency) // "$1.99\n"
Formatter.currency.locale = .br
print(price.currency) // "R$1,99\n"
Formatter.currency.locale = .uk
print(price.currency) // "£1.99\n"
print(price.currencyBR) // "R$1,99\n"
print(price.currencyUS) // "$1.99\n"
Details
Xcode 10.2.1 (10E1001), Swift 5
Solution
import Foundation
class CurrencyFormatter {
static var outputFormatter = CurrencyFormatter.create()
class func create(locale: Locale = Locale.current,
groupingSeparator: String? = nil,
decimalSeparator: String? = nil,
style: NumberFormatter.Style = NumberFormatter.Style.currency) -> NumberFormatter {
let outputFormatter = NumberFormatter()
outputFormatter.locale = locale
outputFormatter.decimalSeparator = decimalSeparator ?? locale.decimalSeparator
outputFormatter.groupingSeparator = groupingSeparator ?? locale.groupingSeparator
outputFormatter.numberStyle = style
return outputFormatter
}
}
extension Numeric {
func toCurrency(formatter: NumberFormatter = CurrencyFormatter.outputFormatter) -> String? {
guard let num = self as? NSNumber else { return nil }
var formatedSting = formatter.string(from: num)
guard let locale = formatter.locale else { return formatedSting }
if let separator = formatter.groupingSeparator, let localeValue = locale.groupingSeparator {
formatedSting = formatedSting?.replacingOccurrences(of: localeValue, with: separator)
}
if let separator = formatter.decimalSeparator, let localeValue = locale.decimalSeparator {
formatedSting = formatedSting?.replacingOccurrences(of: localeValue, with: separator)
}
return formatedSting
}
}
Usage
let price = 12423.42
print(price.toCurrency() ?? "")
CurrencyFormatter.outputFormatter = CurrencyFormatter.create(style: .currencyISOCode)
print(price.toCurrency() ?? "nil")
CurrencyFormatter.outputFormatter = CurrencyFormatter.create(locale: Locale(identifier: "es_ES"))
print(price.toCurrency() ?? "nil")
CurrencyFormatter.outputFormatter = CurrencyFormatter.create(locale: Locale(identifier: "de_DE"), groupingSeparator: " ", style: .currencyISOCode)
print(price.toCurrency() ?? "nil")
CurrencyFormatter.outputFormatter = CurrencyFormatter.create(groupingSeparator: "_", decimalSeparator: ".", style: .currencyPlural)
print(price.toCurrency() ?? "nil")
let formatter = CurrencyFormatter.create(locale: Locale(identifier: "de_DE"), groupingSeparator: " ", decimalSeparator: ",", style: .currencyPlural)
print(price.toCurrency(formatter: formatter) ?? "nil")
Results
$12,423.42
USD12,423.42
12.423,42 €
12 423,42 EUR
12_423.42 US dollars
12 423,42 Euro
Updated for Swift 4 from #Michael Voccola's answer:
extension Double {
var asLocaleCurrency: String {
let formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.locale = Locale.current
let formattedString = formatter.string(from: self as NSNumber)
return formattedString ?? ""
}
}
Note: no force-unwraps, force-unwraps are evil.
Swift 4 TextField Implemented
var value = 0
currencyTextField.delegate = self
func numberFormatting(money: Int) -> String {
let formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.locale = .current
return formatter.string(from: money as NSNumber)!
}
currencyTextField.text = formatter.string(from: 50 as NSNumber)!
func textFieldDidEndEditing(_ textField: UITextField) {
value = textField.text
textField.text = numberFormatting(money: Int(textField.text!) ?? 0 as! Int)
}
func textFieldDidBeginEditing(_ textField: UITextField) {
textField.text = value
}
extension Float {
var convertAsLocaleCurrency :String {
var formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.locale = Locale.current
return formatter.string(from: self as NSNumber)!
}
}
This working for swift 3.1 xcode 8.2.1
Swift 4
formatter.locale = Locale.current
if you want to change locale you can do it like this
formatter.locale = Locale.init(identifier: "id-ID")
// This is locale for Indonesia locale. if you want use as per mobile phone area use it as per upper mention Locale.current
//MARK:- Complete code
let formatter = NumberFormatter()
formatter.numberStyle = .currency
if let formattedTipAmount = formatter.string(from: Int(newString)! as
NSNumber) {
yourtextfield.text = formattedTipAmount
}
add this function
func addSeparateMarkForNumber(int: Int) -> String {
var string = ""
let formatter = NumberFormatter()
formatter.locale = Locale.current
formatter.numberStyle = .decimal
if let formattedTipAmount = formatter.string(from: int as NSNumber) {
string = formattedTipAmount
}
return string
}
using:
let giaTri = value as! Int
myGuessTotalCorrect = addSeparateMarkForNumber(int: giaTri)