10

I have currently a string like this: "8,0" or "4,25" and I need to convert it to a Double, but how would I do that? Do I first replace the , with a .?

I have looked at NSNumberFormatter but that returned nil for every string.

let formatter = NSNumberFormatter()
formatter.minimumFractionDigits = 2
formatter.maximumFractionDigits = 2
let grade = formatter.numberFromString(grade["Cijfer"].stringValue)
print(grade)

What should I use?

luk2302
  • 55,258
  • 23
  • 97
  • 137
jbehrens94
  • 2,356
  • 6
  • 31
  • 59

3 Answers3

17

Use the decimalSeparator:

let formatter = NSNumberFormatter()
formatter.decimalSeparator = ","
let grade = formatter.numberFromString("2,3")

if let doubleGrade = grade?.doubleValue {
    print(doubleGrade)
} else {
    print("not parseable")
}

Prints

2.3

luk2302
  • 55,258
  • 23
  • 97
  • 137
  • And then I can cast the NSNumber to a Double? – jbehrens94 Jan 22 '16 at 09:16
  • @jbehrens94 I included a further code snipper to explain that. – luk2302 Jan 22 '16 at 09:18
  • I also get returns like `9.800000000000001`? – jbehrens94 Jan 22 '16 at 09:18
  • @jbehrens94 yes, that happens, that is how floating point numbers are treated: http://stackoverflow.com/questions/25657869/why-is-swift-giving-me-inaccurate-floating-point-arithmetic-results – luk2302 Jan 22 '16 at 09:20
  • Alright, is there someway I can keep it to a maximum of 2 decimal numbers? – jbehrens94 Jan 22 '16 at 09:21
  • @jbehrens94 no. 9.8 ist not exactly representable in binary. There should not arise any trouble from it. Please accept my answer since it answered your question. Dealing with floating point numbers is an entirely different topic on its own. – luk2302 Jan 22 '16 at 09:22
8

'pure' Swift (no Foundation)

let str = "9,8"
let sstr = str.characters.split(",").joinWithSeparator(["."])
if let d = Double(String(sstr)) {
    print(d) // 9.8
}
user3441734
  • 16,722
  • 2
  • 40
  • 59
  • 9
    or just `str.replacingOccurrences(of: ",", with: ".")` – trickster77777 Dec 03 '18 at 07:20
  • @trickster77777 please, see what is written at the beginning. "no Foundation". Those days (2016) the Foundation framework was only partially available on a platform different from apple. Till now, this function is part of Foundation https://swiftdoc.org/v4.2/type/string/#func-replacingoccurrences-of_with_options_range_ – user3441734 Dec 03 '18 at 08:27
1

Robust string extension

extension String {
    var preparedToDecimalNumberConversion: String {
        split {
            !CharacterSet(charactersIn: "\($0)").isSubset(of: CharacterSet.decimalDigits)
        }.joined(separator: ".")
    }
}

func testPreparingToDecimalNumberConversion() {
    XCTAssertEqual("25.5".preparedToDecimalNumberConversion, "25.5")
    XCTAssertEqual("25,5".preparedToDecimalNumberConversion, "25.5")
    XCTAssertEqual("...,,,25,5,,,".preparedToDecimalNumberConversion, "25.5")
    XCTAssertEqual("25.5,42,..".preparedToDecimalNumberConversion, "25.5.42")
    XCTAssertEqual(".42,..".preparedToDecimalNumberConversion, "42")
    XCTAssertEqual(".36,,,6,..".preparedToDecimalNumberConversion, "36.6")
    XCTAssertEqual("36......6".preparedToDecimalNumberConversion, "36.6")
    XCTAssertEqual("36.,.,.,6".preparedToDecimalNumberConversion, "36.6")

    XCTAssertEqual(Float("25.5".preparedToDecimalNumberConversion), 25.5)
    XCTAssertEqual(Float("25,5".preparedToDecimalNumberConversion), 25.5)
    XCTAssertEqual(Float("...,,,25,5,,,".preparedToDecimalNumberConversion), 25.5)
    XCTAssertEqual(Float("25.5,42,..".preparedToDecimalNumberConversion), nil)
    XCTAssertEqual(Float(".42,..".preparedToDecimalNumberConversion), 42)
}
Andrey Volobuev
  • 862
  • 8
  • 11