Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift - How to convert String to Double

Tags:

swift

People also ask

How to change string to Double in Swift?

Converting string to double To convert a string to a double, we can use the built-in Double() initializer syntax in Swift. The Double() initializer takes the string as an input and returns the double instance. If the string contains invalid characters or invalid format it returns nil.

How do I convert a string to a float in Swift?

If the String contains a valid floating point value, then Swift will assign it to the floatValue constant which will be available within the if let scope. The result of this example will be printed as “Float value = 12.2416”.


Swift 2 Update There are new failable initializers that allow you to do this in more idiomatic and safe way (as many answers have noted, NSString's double value is not very safe because it returns 0 for non number values. This means that the doubleValue of "foo" and "0" are the same.)

let myDouble = Double(myString)

This returns an optional, so in cases like passing in "foo" where doubleValue would have returned 0, the failable intializer will return nil. You can use a guard, if-let, or map to handle the Optional<Double>

Original Post: You don't need to use the NSString constructor like the accepted answer proposes. You can simply bridge it like this:

(swiftString as NSString).doubleValue

Swift 4.2+ String to Double

You should use the new type initializers to convert between String and numeric types (Double, Float, Int). It'll return an Optional type (Double?) which will have the correct value or nil if the String was not a number.

Note: The NSString doubleValue property is not recommended because it returns 0 if the value cannot be converted (i.e.: bad user input).

let lessPrecisePI = Float("3.14")

let morePrecisePI = Double("3.1415926536")
let invalidNumber = Float("alphabet") // nil, not a valid number

Unwrap the values to use them using if/let

if let cost = Double(textField.text!) {
    print("The user entered a value price of \(cost)")
} else {
    print("Not a valid number: \(textField.text!)")
}

You can convert formatted numbers and currency using the NumberFormatter class.

let formatter = NumberFormatter()
formatter.locale = Locale.current // USA: Locale(identifier: "en_US")
formatter.numberStyle = .decimal
let number = formatter.number(from: "9,999.99")

Currency formats

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")

Read more on my blog post about converting String to Double types (and currency).


For a little more Swift feeling, using NSFormatter() avoids casting to NSString, and returns nil when the string does not contain a Double value (e.g. "test" will not return 0.0).

let double = NSNumberFormatter().numberFromString(myString)?.doubleValue

Alternatively, extending Swift's String type:

extension String {
    func toDouble() -> Double? {
        return NumberFormatter().number(from: self)?.doubleValue
    }
}

and use it like toInt():

var myString = "4.2"
var myDouble = myString.toDouble()

This returns an optional Double? which has to be unwrapped.

Either with forced unwrapping:

println("The value is \(myDouble!)") // prints: The value is 4.2

or with an if let statement:

if let myDouble = myDouble {
    println("The value is \(myDouble)") // prints: The value is 4.2
}

Update: For localization, it is very easy to apply locales to the NSFormatter as follows:

let formatter = NSNumberFormatter()
formatter.locale = NSLocale(localeIdentifier: "fr_FR")
let double = formatter.numberFromString("100,25")

Finally, you can use NSNumberFormatterCurrencyStyle on the formatter if you are working with currencies where the string contains the currency symbol.


Another option here is converting this to an NSString and using that:

let string = NSString(string: mySwiftString)
string.doubleValue

Here's an extension method that allows you to simply call doubleValue() on a Swift string and get a double back (example output comes first)

println("543.29".doubleValue())
println("543".doubleValue())
println(".29".doubleValue())
println("0.29".doubleValue())

println("-543.29".doubleValue())
println("-543".doubleValue())
println("-.29".doubleValue())
println("-0.29".doubleValue())

//prints
543.29
543.0
0.29
0.29
-543.29
-543.0
-0.29
-0.29

Here's the extension method:

extension String {
    func doubleValue() -> Double
    {
        let minusAscii: UInt8 = 45
        let dotAscii: UInt8 = 46
        let zeroAscii: UInt8 = 48

        var res = 0.0
        let ascii = self.utf8

        var whole = [Double]()
        var current = ascii.startIndex

        let negative = current != ascii.endIndex && ascii[current] == minusAscii
        if (negative)
        {
            current = current.successor()
        }

        while current != ascii.endIndex && ascii[current] != dotAscii
        {
            whole.append(Double(ascii[current] - zeroAscii))
            current = current.successor()
        }

        //whole number
        var factor: Double = 1
        for var i = countElements(whole) - 1; i >= 0; i--
        {
            res += Double(whole[i]) * factor
            factor *= 10
        }

        //mantissa
        if current != ascii.endIndex
        {
            factor = 0.1
            current = current.successor()
            while current != ascii.endIndex
            {
                res += Double(ascii[current] - zeroAscii) * factor
                factor *= 0.1
                current = current.successor()
           }
        }

        if (negative)
        {
            res *= -1;
        }

        return res
    }
}

No error checking, but you can add it if you need it.