How to Convert a String to Double and Float types using Swift 4
/In Swift 4 you get native String support for working with different numeric types (Float, Double, and Int). But that's not the end of the story, you may need to use the NumberFormatter (NSNumberFormatter) class to convert formatted numbers (1,000,000) or currency ($3.50) in your Swift code.
In this String
to Double
Guide, you'll learn how to convert different types of String
values and how to handle edge cases. Plus you'll learn about a word of caution when converting to NSString
to use the doubleValue
property.
Grab the String to Double Cheatsheet and Swift Playground mentioned below in the toolkit for a quick reference that you can use as you work on your apps.
Convert Swift String
to Double
Use Double
, Float
, CGFloat
to convert floating-point values (real numbers).
let lessPrecisePI = Float("3.14")
let morePrecisePI = Double("3.1415926536")
let width = CGFloat(Double("200.0")!)
Convert Swift String
to Int
Use Int
and the variants like Int32
, UInt64
, etc. to convert integer values.
let wholeNumber = Int("27")
let smallInt = Int16("34")
let largeInt = Int64("39384")
But that's not everything you need to know, because this conversion process can fail, and that gives you an optional Double
(i.e. Double?
), optional Float
(i.e. Float?
), or optional Int
(i.e. Int?
).
How do you use the value if it's wrapped in an optional type?
Get the String Conversion Toolkit
Not everyone learns the same way, get the String Conversion Toolkit so that you can follow along with this guide.
- Print the String to Double Cheatsheet for quick reference
- Explore the code in the Swift Playground (Swift 4)
- Watch an easy to follow video describing how to use NumberFormatter
Optionals: Failure Is an Option
These String
conversions can fail, because you're using a failable initializer for the Double
, Float
, or Int
types.
Why?
If the number is not valid, the conversion from String
to Double
isn't possible. For example, trying to convert from "alphabet" to a Double
doesn't make sense.
let invalidNumber = Double("alphabet") // nil
There's no good number representation for a word like "alphabet", and the result becomes nil
, which means that it's not a number.
To use the converted numbers you'll need to unwrap them—I recommend using the if let
syntax for user input from a UITextField
(or you can use the guard
).
if let cost = Double(textField.text!) {
print("The item is valued at: \(cost)")
} else {
print("Not a valid number: \(textField.text!)")
}
You will need to unwrap the optional to get the value. The if let
syntax above makes it safe to use cost
if it’s a valid number, otherwise you can handle the invalid case in the else expression (i.e.: If the user typed “alphabet” the conversion would fail and print the message "Not a valid number: alphabet").
When Formatted Currency and Formatted Numbers Fail
BUT, the same thing can happen if you're trying to convert currency numbers ($3.49), or even formatted numbers with grouping separators (4,300.99). And that's because the initializers will not use locale information.
let failedCurrency = Double("$3.49") // nil
let failedFormattedNumber = Double("4,300.99") // nil
If you need to convert currency or formatted number String
's read below (and if you want to convert a number to a currency String read How to use NumberFormatter in Swift.
What Are You Trying to Do?
Depending on the reason that you need convert between String
and Double
will change how I would recommend moving forward.
- Are you getting user input from a UITextField (user input) or is it data from a database?
- Are you working with currencies?
- Are the numbers formatted or unformatted?
- Is your app a simple test app, or is it an app you plan to publish?
- Do you need to support different localizations? (different countries write numbers differently!)
Download the Number Converter Playground
Convert Double
, Float
, or Int
to String
You can do the reverse conversion from a Double
to a String
by using one of the many String
initializers. (These methods don't fail!)
let costString = String(9.99)
let ageString = String(18)
As long as the number isn’t optional the resulting value will be a String
type, not a String?
type.
String Interpolation
String interpolation is another method to convert numbers to String.
let yearsAgo: Int = 10
let outputString = "I had \(3) pairs of running shoes \(yearsAgo) years ago."
Converting a Formatted Decimal Number String
Using the Double
initializer is not going to work when you need to convert numbers from different counties. The initializer is not locale aware, and differences in how numbers are formatted in other languages is going to make it fail.
For example the number 9,999.99
(English USA) would be written as:
- Germany:
9.999,99
- France:
9 999,99
If you need to work with different locales you have two options:
Use
NumberFormatter
with your user's current local, or a specific iOS locale identifier for another country.. TheNumberFormatter
is the most robust and can handle different locale's grouping separators for the thousands separators.let formatter = NumberFormatter() formatter.locale = Locale.current // USA: Locale(identifier: "en_US") formatter.numberStyle = .decimal let number = formatter.number(from: "9,999.99") let frenchLocale = Locale(identifier: "fr_FR") let germanLocale = Locale(identifier: "de_DE") formatter.locale = frenchLocale let numberFrance2 = formatter.number(from: "9 999,99") formatter.locale = germanLocale let numberGerman2 = formatter.number(from: "9.999,99")
All of the formatted numbers will be of type NSNumber
, which has a doubleValue property.
Use
NSDecimalNumber
for accurate numbers. Your currency data should be stored as aNSDecimalNumber
(not a Double or a Float). I only show the simple Double or Float examples because they are easier to start using.let usLocale = Locale(identifier: "en_US") let frenchLocale = Locale(identifier: "fr_FR") let germanLocale = Locale(identifier: "de_DE") // Convert decimal numbers (cannot have grouping separators!) let numberUSA = NSDecimalNumber(string: "1000.0", locale: usLocale) let numberFrance = NSDecimalNumber(string: "9999,99", locale: frenchLocale) let numberGermany = NSDecimalNumber(string: "9999,99", locale: germanLocale)
The problem with Double
is that it's not 100% accurate. It loses precision for decimal values that exceed it's maximum value, and it starts to round your numbers. When it comes to money you don't want to start losing fractions of a dollar in your application.
Converting a Currency String
If you need to convert a user String
you should store all your numbers as decimal numbers. a numeric currency you need to use NSDecimalNumber
.
Use NumberFormatter
with the currency style to convert formatted currency String
's
let usLocale = Locale(identifier: "en_US")
let frenchLocale = Locale(identifier: "fr_FR")
let germanLocale = Locale(identifier: "de_DE")
let englishUKLocale = Locale(identifier: "en_GB") // United Kingdom
formatter.numberStyle = .currency
formatter.locale = usLocale
let usCurrency = formatter.number(from: "$9,999.99")
formatter.locale = frenchLocale
let frenchCurrency = formatter.number(from: "9999,99€")
// Note: "9 999,99€" fails with grouping separator
// Note: "9999,99 €" fails with a space before the €
formatter.locale = germanLocale
let germanCurrency = formatter.number(from: "9999,99€")
// Note: "9.999,99€" fails with grouping separator
formatter.locale = englishUKLocale
let englishUKCurrency = formatter.number(from: "£9,999.99")
Warning About NSString
You may find code that uses the NSString
conversion to get access to a doubleValue
property. I don't recommend using this approach.
let cost = ("9.99" as NSString).doubleValue // not recommended
BUT, you can have problems if you use this code, since the following two lines will return the same result:
let cost1 = ("abc" as NSString).doubleValue // invalid returns 0, not an optional. (not recommended)
let cost2 = ("0.00" as NSString).doubleValue // also returns 0
It's a problem because both lines of code result in 0, but only one of the lines was actually 0, while the other was an error. A failure to parse a number using NSString results in 0.
This error mode is not safe and will cause logic errors in your app! Use NumberFormatter
instead.
Watch the String to Number Conversion Video
Questions or Comments?
If you have a question, leave a comment down below.
And if you need to see how this code works in action, get the toolkit above so that you can watch me walk through the process of converting numbers.