141

Before I updated xCode 6, I had no problems casting a double to a string but now it gives me an error

var a: Double = 1.5
var b: String = String(a)

It gives me the error message "double is not convertible to string". Is there any other way to do it?

seralouk
  • 30,938
  • 9
  • 118
  • 133
tim_yng
  • 2,591
  • 4
  • 18
  • 20

16 Answers16

258

It is not casting, it is creating a string from a value with a format.

let a: Double = 1.5
let b: String = String(format: "%f", a)

print("b: \(b)") // b: 1.500000

With a different format:

let c: String = String(format: "%.1f", a)

print("c: \(c)") // c: 1.5

You can also omit the format property if no formatting is needed.

Evan93
  • 155
  • 11
zaph
  • 111,848
  • 21
  • 189
  • 228
  • 1
    What about a double with a bigger fraction digits number? Like let a = 2.34934340320 let stringValue = String(format: "%f", a) will give 2.349343 – Nico Mar 21 '15 at 12:33
  • 1
    The display can be controlled with the printf formatting options, see: [String Format Specifiers](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html) and [printf(3)](https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/printf.3.html). – zaph Mar 21 '15 at 13:14
  • 3
    You just have to change your format to control the amount of digits: `format:"%.1f" = 1 digit // 1.5`; `format:"%.5f" = 5 digits // 1.50000` – Megaetron Jul 09 '15 at 01:19
  • 3
    Please update your answer, in Swift 2.1 you just have to do `String(yourDouble)`. – Alexandre G. Feb 24 '16 at 10:54
  • The answer is about using `format:` to control the output display, note the second example output, note `format:"%.1f"`. Updated `print` for 2.1. – zaph Feb 24 '16 at 12:55
  • 1
    You can use let instead of var. There is not need now to call it several times. – J A S K I E R Apr 30 '18 at 00:22
  • @zaph change the test value to 1.978, It will out put 2.0 :( – mmk Jul 27 '22 at 01:34
112
let double = 1.5 
let string = double.description

update Xcode 7.1 • Swift 2.1:

Now Double is also convertible to String so you can simply use it as you wish:

let double = 1.5
let doubleString = String(double)   // "1.5"

Swift 3 or later we can extend LosslessStringConvertible and make it generic

Xcode 11.3 • Swift 5.1 or later

extension LosslessStringConvertible { 
    var string: String { .init(self) } 
}

let double = 1.5 
let string = double.string  //  "1.5"

For a fixed number of fraction digits we can extend FloatingPoint protocol:

extension FloatingPoint where Self: CVarArg {
    func fixedFraction(digits: Int) -> String {
        .init(format: "%.*f", digits, self)
    }
}

If you need more control over your number format (minimum and maximum fraction digits and rounding mode) you can use NumberFormatter:

extension Formatter {
    static let number = NumberFormatter()
}

extension FloatingPoint {
    func fractionDigits(min: Int = 2, max: Int = 2, roundingMode: NumberFormatter.RoundingMode = .halfEven) -> String {
        Formatter.number.minimumFractionDigits = min
        Formatter.number.maximumFractionDigits = max
        Formatter.number.roundingMode = roundingMode
        Formatter.number.numberStyle = .decimal
        return Formatter.number.string(for: self) ?? ""
    }
}

2.12345.fractionDigits()                                    // "2.12"
2.12345.fractionDigits(min: 3, max: 3, roundingMode: .up)   // "2.124"
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
  • 1
    is this a hack or is this a legit way to do it? would it cause any problems with different ios versions? – Esqarrouth Dec 30 '14 at 20:23
  • 3
    No, you won't have any problems with different ios versions. It also works for OSX. BTW this is what you get when doing String Interpolation with a Double or an Int. – Leo Dabus Dec 30 '14 at 20:26
  • Very useful. You can't format like %f. And It works also for Int so you have one way to do it for two types. – Patrik Vaberer Apr 09 '15 at 11:56
  • This won't work for 0.00001, it becomes "1e-05" as a string. –  Mar 10 '16 at 13:34
  • Replace `String(format: "%.\(digits)f", self as! CVarArg)` with `String(format: "%.*f", digits, self as! CVarArg)` – rmaddy Oct 27 '19 at 18:09
28

In addition to @Zaph's answer, you can create an extension on Double:

extension Double {
    func toString() -> String {
        return String(format: "%.1f",self)
    }
}

Usage:

var a:Double = 1.5
println("output: \(a.toString())")  // output: 1.5
Sam Spencer
  • 8,492
  • 12
  • 76
  • 133
Maxim Shoustin
  • 77,483
  • 27
  • 203
  • 225
  • 1
    @MaximShoustin The OP does not have enough rep to up vote and answer, 15 is required. I also disagree with creating an Extension, when the statement: `a.toString()` is seen by another developer there will definitely be a WTF moment. – zaph Aug 16 '14 at 17:41
  • 2
    @Zaph why not. For sure you can add some prefix and change it to `myToString()` to be sure that its custom definition. But like in other languages prototyping leads to avoiding code duplicate and good maintenance. – Maxim Shoustin Aug 16 '14 at 18:58
  • @MaximShoustin newbie question: what's the difference between `println("output: \(a.toString())")` and `println("output: \(a)")`. Second option doesn't cause compile errors. Is this option a bad practice? – Alex Guerrero Nov 27 '14 at 10:29
  • Is there a clever way to write such an extension to Double or FloatingPoint that would work on an Optional Double to return an empty String? – Kinergy Feb 01 '19 at 18:05
  • @Kinergy `extension Optional where Wrapped: LosslessStringConvertible {` `var string: String {` `guard let unwrapped = self else { return "" }` `return .init(unwrapped)` `}` `}` – Leo Dabus Sep 27 '20 at 03:26
12

Swift 3+: Try these line of code

let num: Double = 1.5

let str = String(format: "%.2f", num)
Shiv Kumar
  • 932
  • 7
  • 12
10

to make anything a string in swift except maybe enum values simply do what you do in the println() method

for example:

var stringOfDBL = "\(myDouble)"
eric bob
  • 235
  • 2
  • 11
5

There are many answers here that suggest a variety of techniques. But when presenting numbers in the UI, you invariably want to use a NumberFormatter so that the results are properly formatted, rounded, and localized:

let value = 10000.5

let formatter = NumberFormatter()
formatter.numberStyle = .decimal

guard let string = formatter.string(for: value) else { return }
print(string) // 10,000.5

If you want fixed number of decimal places, e.g. for currency values

let value = 10000.5

let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.maximumFractionDigits = 2
formatter.minimumFractionDigits = 2

guard let string = formatter.string(for: value) else { return }
print(string) // 10,000.50

But the beauty of this approach, is that it will be properly localized, resulting in 10,000.50 in the US but 10.000,50 in Germany. Different locales have different preferred formats for numbers, and we should let NumberFormatter use the format preferred by the end user when presenting numeric values within the UI.

Needless to say, while NumberFormatter is essential when preparing string representations within the UI, it should not be used if writing numeric values as strings for persistent storage, interface with web services, etc.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • 1
    Yes, this is the absolute correct answer, and the only one which keeps pain with locals away. – flymg Nov 01 '21 at 18:20
3

This function will let you specify the number of decimal places to show:

func doubleToString(number:Double, numberOfDecimalPlaces:Int) -> String {
    return String(format:"%."+numberOfDecimalPlaces.description+"f", number)
}

Usage:

let numberString = doubleToStringDecimalPlacesWithDouble(number: x, numberOfDecimalPlaces: 2)
MobileMon
  • 8,341
  • 5
  • 56
  • 75
  • Replace `String(format:"%."+numberOfDecimalPlaces.description+"f", number)` with `String(format:"%.*f", numberOfDecimalPlaces, number)` – rmaddy Oct 27 '19 at 18:10
3

Swift 4: Use following code

let number = 2.4
let string = String(format: "%.2f", number)
Abhishek Jain
  • 4,557
  • 2
  • 32
  • 31
  • 1
    It's the same solution as the one given by @shiv-kumar https://stackoverflow.com/a/46487485/2227743 – Eric Aya Dec 15 '17 at 16:01
2

In swift 3:

var a: Double = 1.5
var b: String = String(a)
carlson
  • 148
  • 2
  • 6
1

In swift 3 it is simple as given below

let stringDouble =  String(describing: double)
Sebin Roy
  • 834
  • 9
  • 10
1

I would prefer NSNumber and NumberFormatter approach (where need), also u can use extension to avoid bloating code

extension Double {

   var toString: String {
      return NSNumber(value: self).stringValue
   }

}

U can also need reverse approach

extension String {

    var toDouble: Double {
        return Double(self) ?? .nan
    }

}
  • why are you returning optional but assigning .nan if nil? You should do either one or another. Not both. Btw Whats wrong with using the String initializer ? You can also make it more generic extending `LossLessStringConvertible` protocol instead of extending Double `extension LosslessStringConvertible { var string: String { return .init(self) } }` – Leo Dabus Jun 23 '19 at 15:14
  • U are right returning Double? Is a refuse since I already check it is nil and return NaN – Giuseppe Mazzilli Jun 25 '19 at 22:03
0
var b = String(stringInterpolationSegment: a)

This works for me. You may have a try

Miriam Farber
  • 18,986
  • 14
  • 61
  • 76
sevenkplus
  • 178
  • 1
  • 12
0

In Swift 4 if you like to modify and use a Double in the UI as a textLabel "String" you can add this in the end of your file:

    extension Double {
func roundToInt() -> Int{
    return Int(Darwin.round(self))
}

}

And use it like this if you like to have it in a textlabel:

currentTemp.text = "\(weatherData.tempCelsius.roundToInt())"

Or print it as an Int:

print(weatherData.tempCelsius.roundToInt())
Patrik Rikama-Hinnenberg
  • 1,362
  • 1
  • 16
  • 27
0

Swift 5: Use following code

extension Double {

    func getStringValue(withFloatingPoints points: Int = 0) -> String {
        let valDouble = modf(self)
        let fractionalVal = (valDouble.1)
        if fractionalVal > 0 {
            return String(format: "%.*f", points, self)
        }
        return String(format: "%.0f", self)
    }
}
g212gs
  • 863
  • 10
  • 26
0

You shouldn't really ever cast a double to a string, the most common reason for casting a float to a string is to present it to a user, but floats are not real number and can only approximate lots of values, similar to how ⅓ can not be represented as a decimal number with a finite number of decimal places. Instead keep you values as float for all their use, then when you want to present them to the user, use something like NumberFormater to convert them for your. This stage of converting for user presentation is what something like your viewModel should do.

Nathan Day
  • 5,981
  • 2
  • 24
  • 40
0

Use this. Text(String(format: "%.2f", doubleValue))

Eray Hamurlu
  • 657
  • 7
  • 9