Swift - So konvertieren Sie einen String in Double

241

Ich versuche ein BMI-Programm in schneller Sprache zu schreiben. Und ich habe dieses Problem: Wie konvertiere ich einen String in einen Double?

In Objective-C kann ich Folgendes tun:

double myDouble = [myString doubleValue];

Aber wie kann ich das in Swift erreichen?

Oh ja
quelle
1
Dies hat sich in Swift 2 geändert, siehe die neue Antwort mit dem neuen Double () Failable-Initialisierer: stackoverflow.com/a/32850058/276626
Paul Solt

Antworten:

205

Swift 4.2+ String to Double

Sie sollten die neuen Typinitialisierer verwenden, um zwischen String- und numerischen Typen (Double, Float, Int) zu konvertieren. Es wird ein optionaler Typ (Double?) Zurückgegeben, der den richtigen Wert oder Null hat, wenn der String keine Zahl war.

Hinweis: Die NSString doubleValue-Eigenschaft wird nicht empfohlen, da sie 0 zurückgibt, wenn der Wert nicht konvertiert werden kann (dh: schlechte Benutzereingaben).

let lessPrecisePI = Float("3.14")

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

Packen Sie die Werte aus, um sie mit if / let zu verwenden

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

Mit der NumberFormatterKlasse können Sie formatierte Zahlen und Währungen konvertieren .

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

Währungsformate

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

Lesen Sie mehr in meinem Blog-Beitrag über die Konvertierung von String in Double-Typen (und Währung) .

Paul Solt
quelle
2
Ein weiteres Problem ist, dass keine Zahlen in einem anderen Gebietsschema als 1.000,00 unterstützt werden. Wenn Sie andere Formate wie 1 000,00 verwenden, werden die 2 Dezimalstellen am Ende abgeschnitten. Zumindest passiert dies für Objective-C. - Gemäß Apple-Dokumentation: (Sie sind nicht länderspezifisch) Die folgenden praktischen Methoden überspringen alle anfängliche Leerzeichen (whitespaceSet) und ignorieren nachfolgende Zeichen. Sie kennen das Gebietsschema nicht. NSScanner oder NSNumberFormatter können für eine leistungsfähigere und länderspezifische Analyse von Zahlen verwendet werden.
mskw
@mskw Ich habe zusätzliche Details zur Verwendung des NumberFormatter zum Parsen der Währung hinzugefügt. In meinem Code werde ich mehrere Formatierungsversuche zur Konvertierung mithilfe der if / let-Syntax aneinanderreihen, damit ich sowohl währungsformatierte Zahlen (1.000,00 USD) als auch formatierte Zahlen (1.000 USD) analysieren kann. Sie wissen nicht immer, wie der Benutzer Zahlen eingibt. Daher ist es ideal, beide mit einer Gruppe von if / let-Anweisungen unterstützen zu können.
Paul Solt
276

Swift 2 Update Es gibt neue fehlgeschlagene Initialisierer, mit denen Sie dies idiomatischer und sicherer tun können (wie viele Antworten festgestellt haben, ist der doppelte Wert von NSString nicht sehr sicher, da er 0 für Nicht-Zahlenwerte zurückgibt. Dies bedeutet, dass die doubleValuevon "foo"und "0"sind das Gleiche.)

let myDouble = Double(myString)

Dies gibt eine optionale, so in Fällen wie beiläufig , "foo"wo doubleValue0 zurückgegeben hätte, der failable intializer zurückkehren wird nil. Sie können ein verwenden guard, if-letoder mapzu handhaben dieOptional<Double>

Originaler Beitrag: Sie müssen den NSString-Konstruktor nicht wie in der akzeptierten Antwort vorgeschlagen verwenden. Sie können es einfach so überbrücken:

(swiftString as NSString).doubleValue
Jarsen
quelle
5
ohai, Jarsen. Ein Nachteil dieses Ansatzes ist, dass er nicht fehlschlägt, wenn die Zeichenfolge kein gültiges Double ist. Stattdessen erhalten Sie nur 0.0. Das heißt, das Ergebnis von - [NSString doubleValue]ist Doublein Bezug auf Double?( Optional<Double>) schnell . Dies unterscheidet sich von der Swift String-Funktion, toInt()die zurückgibt Int?und in den Dokumenten angibt, dass "... nur Zeichenfolgen akzeptiert werden, die dem regulären Ausdruck" [- +]? [0-9] + "entsprechen."
Derrick Hathaway
Ja, .toInt()wäre besser. Dies war jedoch eher eine Antwort darauf, wie man genau dasselbe macht, aber in Swift.
Jarsen
Dieser Ansatz ist eng mit Foundation verbunden und funktioniert wahrscheinlich nicht bei Swift-Implementierungen, die nicht von Apple stammen.
Erik Kerber
5
In Swift 2.0 ist Double.init?(_ text: String)jetzt ein fehlgeschlagener Initialisierer verfügbar.
Mixel
3
Dies ist nicht der beste Ansatz. Dies schlägt je nach Dezimaltrennzeichen fehl. Es wird gut mit '.' aber nicht mit ','. NSNumberFormatter unterstützt das in der aktuellen Lokalisierung verwendete Dezimaltrennzeichen.
Julian Król
75

Für ein etwas schnelleres Gefühl NSFormatter()vermeidet die Verwendung das Umwandeln in NSStringund kehrt zurück, nilwenn die Zeichenfolge keinen DoubleWert enthält (z. B. "test" wird nicht zurückgegeben 0.0).

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

Alternativ können Sie den StringTyp von Swift erweitern :

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

und benutze es wie toInt():

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

Dies gibt eine Option zurück, Double?die ausgepackt werden muss.

Entweder mit erzwungenem Auspacken:

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

oder mit einer if let-Anweisung:

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

Update: Für die Lokalisierung ist es sehr einfach, Gebietsschemas wie folgt auf den NSFormatter anzuwenden:

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

Schließlich können Sie NSNumberFormatterCurrencyStyleden Formatierer verwenden, wenn Sie mit Währungen arbeiten, bei denen die Zeichenfolge das Währungssymbol enthält.

RyuX51
quelle
Ich mag die Idee, die String-Klasse für Apps zu erweitern, die die Konvertierung an mehreren Stellen verwenden. Ich sehe jedoch nicht den Vorteil der Komplexität des Aufrufs von NSNumberFormatter, da die Umwandlung in NSString und die Verwendung von .doubleValue mindestens genauso direkt und einfacher zu lesen und zu merken scheint.
Clearlight
12
Tatsächlich besteht der Vorteil der Verwendung von NSNumberFormatter () darin, dass die Methode numberFromString: null zurückgibt, wenn die Zeichenfolge Zeichen enthält, die kein Double bilden. Das Problem mit doubleValue unter NSString ist, dass unabhängig davon immer ein double zurückgegeben wird (z. B. 0.0 für "test"). Wenn Sie also mit allen Arten von Zeichenfolgen arbeiten und testen möchten, ob die Zeichenfolge nur ein Doppelzeichen ist, keine zusätzlichen Zeichen, ist die Verwendung von NSNumberFormatter der richtige Weg.
Dirkgroten
4
Dies schlägt auf Französisch fehl.
Peter K.
1
Dies ist eine großartige Lösung, aber wenn Sie nur diesen Code verwenden, funktioniert dies nicht in Ländern, in denen Kommas als Trennzeichen verwendet werden (einschließlich Frankreich als @PeterK. Erwähnt). Ich habe versucht, einen Kommentar mit der Lösung zu schreiben, aber er war zu lang, sodass ich stattdessen eine Antwort geben musste. Los geht's: Geänderte Lösung
Jacob R
53

Eine andere Option besteht darin, dies in ein zu konvertieren NSStringund Folgendes zu verwenden:

let string = NSString(string: mySwiftString)
string.doubleValue
Keith Smiley
quelle
13
Ich wünschte, es gäbe einen schöneren Weg, dies zu tun. Wie kann ich beispielsweise feststellen, ob das Parsen fehlgeschlagen ist?
Ryan Hoffman
2
@ RyanHoffman Leider hat der NSString doubleValue-Vertrag nichts davon geliefert. Alles, was Sie erhalten, ist 0.0, wenn die Zeichenfolge nicht mit einer gültigen Darstellung einer Zahl, HUGE_VAL und -HUGE_VAL, bei Überlauf / Unterlauf beginnt. Wenn Sie wissen möchten, warum das Parsen fehlgeschlagen ist, sollten Sie sich NSNumberFormatter ansehen, das für eine robustere Konvertierung von Zahlen und Zeichenfolgen entwickelt wurde.
Jarsen
Da es schwierig sein kann, diese Antwort zu finden, ist sie hier:(swiftString as NSString).doubleValue
LearnCocos2D
24

Hier ist eine Erweiterungsmethode, mit der Sie einfach doubleValue () für eine Swift-Zeichenfolge aufrufen und ein Double Back erhalten können (Beispielausgabe steht an erster Stelle)

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

Hier ist die Erweiterungsmethode:

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
    }
}

Keine Fehlerprüfung, aber Sie können es hinzufügen, wenn Sie es brauchen.

Millie Smith
quelle
20

Ab Swift 1.1 können Sie direkt an Stringden const char *Parameter übergeben.

import Foundation

let str = "123.4567"
let num = atof(str) // -> 123.4567

atof("123.4567fubar") // -> 123.4567

Wenn Sie nicht veraltet mögen atof:

strtod("765.4321", nil) // -> 765.4321

Eine Einschränkung: Das Verhalten der Konvertierung unterscheidet sich von NSString.doubleValue.

atofund strtodakzeptiere 0xvorangestellte Hex-Zeichenfolge:

atof("0xffp-2") // -> 63.75
atof("12.3456e+2") // -> 1,234.56
atof("nan") // -> (not a number)
atof("inf") // -> (+infinity)

Wenn Sie .doubleValueVerhalten bevorzugen , können wir weiterhin CFStringBridging verwenden:

let str = "0xff"
atof(str)                      // -> 255.0
strtod(str, nil)               // -> 255.0
CFStringGetDoubleValue(str)    // -> 0.0
(str as NSString).doubleValue  // -> 0.0
Rintaro
quelle
Ich bin ein Fan dieses Ansatzes, anstatt zu gießen NSString.
Sam Soffes
10

In Swift 2.0 ist es am besten, nicht wie ein Objective-C-Entwickler zu denken. Sie sollten also nicht "einen String in einen Double konvertieren", sondern "einen Double aus einem String initialisieren". Apple-Dokument hier: https://developer.apple.com/library/ios//documentation/Swift/Reference/Swift_Double_Structure/index.html#//apple_ref/swift/structctr/Double/s:FSdcFMSdFSSGSqSd_

Es ist eine optionale Init, sodass Sie mit dem Null-Koaleszenz-Operator (??) einen Standardwert festlegen können. Beispiel:

let myDouble = Double("1.1") ?? 0.0
Toom
quelle
Double.init?(_ text: String)werden in Swift 2.0 verfügbar. Sie sollten dies erwähnen. Andere Antworten hier sind nicht, weil die Leute wie Objective-C-Entwickler denken, sondern weil dieser Initialisierer früher nicht verfügbar war.
Mixel
In der Tat hast du recht. Dies ist nur in Swift 2.0 verfügbar, ich werde es erwähnen :) Aber wie in anderen Sprachen initialisieren Sie einen Typ mit einem anderen und sollten nicht erwarten, dass ein Typ in einen anderen konvertiert werden kann. Lange Debatte, aber als Obj-C-Entwickler habe ich viele schlechte Praktiken beim Codieren mit Swift und dies ist eine davon :)
Toom
10

In SWIFT 3 können Sie Folgendes verwenden:

if let myDouble = NumberFormatter().number(from: yourString)?.doubleValue {
   print("My double: \(myDouble)")
}

Hinweis: - Wenn eine Zeichenfolge andere Zeichen als numerische Ziffern oder für das Gebietsschema geeignete Gruppen- oder Dezimaltrennzeichen enthält, schlägt die Analyse fehl. - Alle führenden oder nachfolgenden Leerzeichen in einer Zeichenfolge werden ignoriert. Beispielsweise erzeugen die Zeichenfolgen "5", "5" und "5" alle die Nummer 5.

Entnommen aus der Dokumentation: https://developer.apple.com/reference/foundation/numberformatter/1408845-number

Jorge Luis Jiménez
quelle
10

Ich habe die gesuchte Antwort nicht gesehen. Ich poste hier nur meine, falls es jemandem helfen kann. Diese Antwort ist nur gültig , wenn Sie kein bestimmtes Format benötigen .

Swift 3

extension String {
    var toDouble: Double {
        return Double(self) ?? 0.0
    }
}
TomCobo
quelle
9

Versuche dies:

   var myDouble = myString.bridgeToObjectiveC().doubleValue
   println(myDouble)

HINWEIS

In Beta 5 entfernt. Das funktioniert nicht mehr?

CW0007007
quelle
1
bridgeToObjectiveC () wurde in Xcode 6 Beta 5 entfernt. Die Methode von Herrn Smiley ist die schnellste, die ich im Moment gefunden habe
faraquet99
7

Dies baut auf der Antwort von @Ryu auf

Seine Lösung ist großartig, solange Sie sich in einem Land befinden, in dem Punkte als Trennzeichen verwendet werden. Standardmäßig NSNumberFormatterwird das Gebietsschema des Geräts verwendet. Daher schlägt dies in allen Ländern fehl, in denen ein Komma als Standardtrennzeichen verwendet wird (einschließlich Frankreich als @PeterK. Erwähnt), wenn die Zahl Punkte als Trennzeichen verwendet (was normalerweise der Fall ist). Um das Gebietsschema dieses NSNumberFormatter auf US festzulegen und daher Punkte als Trennzeichen zu verwenden, ersetzen Sie die Zeile

return NSNumberFormatter().numberFromString(self)?.doubleValue

mit

let numberFormatter = NSNumberFormatter()
numberFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
return numberFormatter.numberFromString(self)?.doubleValue

Daher wird der vollständige Code

extension String {
    func toDouble() -> Double? {
        let numberFormatter = NSNumberFormatter()
        numberFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
        return numberFormatter.numberFromString(self)?.doubleValue
    }
}

Um dies zu nutzen, rufen Sie einfach an "Your text goes here".toDouble()

Dies gibt eine optionale zurück Double?

Wie @Ryu erwähnt hat, können Sie entweder das Auspacken erzwingen:

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

oder verwenden Sie eine if letAussage:

if let myDouble = myDouble {
    println("The value is \(myDouble)") // prints: The value is 4.2
}
Jacob R.
quelle
1
Das ist die richtige Antwort. Die Swift 3 Version wird NumberFormatter().number(from: myString)?.doubleValue
Nicole Leo
7

SWIFT 4

extension String {
    func toDouble() -> Double? {
        let numberFormatter = NumberFormatter()
        numberFormatter.locale = Locale(identifier: "en_US_POSIX")
        return numberFormatter.number(from: self)?.doubleValue
    }
}
t4nhpt
quelle
6

Swift 4.0

Versuche dies

 let str:String = "111.11"
 let tempString = (str as NSString).doubleValue
 print("String:-",tempString)
Vishal Vaghasiya
quelle
6

Schnell: 4 und 5

Es gibt möglicherweise zwei Möglichkeiten, dies zu tun:

  1. String -> Int -> Double:

    let strNumber = "314"
    if let intFromString = Int(strNumber){
        let dobleFromInt = Double(intFromString)
        print(dobleFromInt)
    }
  2. String -> NSString -> Double

    let strNumber1 = "314"
    let NSstringFromString = NSString(string: strNumber1)
    let doubleFromNSString = NSstringFromString.doubleValue
    print(doubleFromNSString)

Verwenden Sie es, wie Sie möchten, je nach Bedarf des Codes.

Abhirajsinh Thakore
quelle
Die erste Methode funktioniert bei mir nicht, die zweite jedoch ziemlich gut.
Saurabh
@ Saurabh, kannst du bitte näher darauf eingehen, was deine Saite war?
Abhirajsinh Thakore
5

Bitte überprüfen Sie es auf dem Spielplatz!

let sString = "236.86"

var dNumber = NSNumberFormatter().numberFromString(sString)
var nDouble = dNumber!
var eNumber = Double(nDouble) * 3.7

Übrigens in meinem Xcode

.toDouble () - existiert nicht

.doubleValue erstellt Wert 0.0 aus nicht numerischen Zeichenfolgen ...

Mamazur
quelle
4

1.

let strswift = "12"
let double = (strswift as NSString).doubleValue

2.

var strswift= "10.6"
var double : Double = NSString(string: strswift).doubleValue 

Kann diese Hilfe für Sie sein.

Daxesh Nagar
quelle
4

Wie bereits erwähnt, ist der beste Weg, dies zu erreichen, das direkte Casting:

(myString as NSString).doubleValue

Darauf aufbauend können Sie eine raffinierte native Swift String-Erweiterung erstellen:

extension String {
    var doubleValue: Double {
        return (self as NSString).doubleValue
    }
}

Auf diese Weise können Sie direkt verwenden:

myString.doubleValue

Welches wird das Casting für Sie durchführen. Wenn Apple doubleValueder nativen Zeichenfolge eine hinzufügt , müssen Sie nur die Erweiterung entfernen, und der Rest Ihres Codes wird automatisch ordnungsgemäß kompiliert!

Firo
quelle
Apples Methode würde .toDouble heißen ... genau wie toInt. Es ist eine seltsame Auslassung. Wird wahrscheinlich in einer zukünftigen Swift-Version behoben. Ich mag die Erweiterungsmethode am besten, hält den Code sauber.
n13
Der Rückgabewert sollte ein Double NOT a Float sein
Leo Dabus
4

SWIFT 3

Heutzutage gibt es eine Standardmethode:

public init?(_ text: String)der DoubleKlasse.

Es kann für alle Klassen verwendet werden.

let c = Double("-1.0") let f = Double("0x1c.6") let i = Double("inf") , etc.

Vyacheslav
quelle
2

Erweiterung mit optionalem Gebietsschema

Swift 2.2

extension String {
    func toDouble(locale: NSLocale? = nil) -> Double? {
        let formatter = NSNumberFormatter()
        if let locale = locale {
            formatter.locale = locale
        }
        return formatter.numberFromString(self)?.doubleValue
    }
}

Swift 3.1

extension String {
    func toDouble(_ locale: Locale) -> Double {
        let formatter = NumberFormatter()
        formatter.numberStyle = .decimal
        formatter.locale = locale
        formatter.usesGroupingSeparator = true
        if let result = formatter.number(from: self)?.doubleValue {
            return result
        } else {
            return 0
        }
    }
}
imike
quelle
1
Ich habe Swift 3.1 Beispiel hinzugefügt. Was meinst du mit "... und füge ein Beispiel für das Gebietsschema hinzu"? 🙂
Imike
1

Oder Sie könnten tun:

var myDouble = Double((mySwiftString.text as NSString).doubleValue)
jr00n
quelle
1

Sie können StringEx verwenden . Es erweitert sich Stringmit Konvertierungen von Zeichenfolgen in Zahlen einschließlich toDouble().

extension String {
    func toDouble() -> Double?
}

Es überprüft die Zeichenfolge und schlägt fehl, wenn sie nicht in double konvertiert werden kann.

Beispiel:

import StringEx

let str = "123.45678"
if let num = str.toDouble() {
    println("Number: \(num)")
} else {
    println("Invalid string")
}
Stas
quelle
1

Swift 4

extension String {
    func toDouble() -> Double {
        let nsString = self as NSString
        return nsString.doubleValue
    }
}
Aitor Lucas
quelle
0

Was auch funktioniert:

// Init default Double variable
var scanned: Double()

let scanner = NSScanner(string: "String to Scan")
scanner.scanDouble(&scanned)

// scanned has now the scanned value if something was found.
Bijan
quelle
HINWEIS: 'scanDouble' wurde in iOS 13.0
uplearnedu.com
0

Verwenden Sie diesen Code in Swift 2.0

let strWithFloat = "78.65" let floatFromString = Double(strWithFloat)

Maninderjit Singh
quelle
0

Mit Scannerin einigen Fällen ist eine sehr bequeme Art und Weise Zahlen der Extraktion aus einem String. Und es ist fast so leistungsfähig wie NumberFormatterbeim Dekodieren und Behandeln verschiedener Zahlenformate und Gebietsschemas. Es kann Zahlen und Währungen mit unterschiedlichen Dezimal- und Gruppentrennzeichen extrahieren.

import Foundation
// The code below includes manual fix for whitespaces (for French case)
let strings = ["en_US": "My salary is $9,999.99",
               "fr_FR": "Mon salaire est 9 999,99€",
               "de_DE": "Mein Gehalt ist 9999,99€",
               "en_GB": "My salary is £9,999.99" ]
// Just for referce
let allPossibleDecimalSeparators = Set(Locale.availableIdentifiers.compactMap({ Locale(identifier: $0).decimalSeparator}))
print(allPossibleDecimalSeparators)
for str in strings {
    let locale = Locale(identifier: str.key)
    let valStr = str.value.filter{!($0.isWhitespace || $0 == Character(locale.groupingSeparator ?? ""))}
    print("Value String", valStr)

    let sc = Scanner(string: valStr)
    // we could do this more reliably with `filter` as well
    sc.charactersToBeSkipped = CharacterSet.decimalDigits.inverted
    sc.locale = locale

    print("Locale \(locale.identifier) grouping separator: |\(locale.groupingSeparator ?? "")| . Decimal separator: \(locale.decimalSeparator ?? "")")
    while !(sc.isAtEnd) {
        if let val = sc.scanDouble() {
            print(val)
        }

    }
}

Es gibt jedoch Probleme mit Trennzeichen, die als Worttrennzeichen aufgefasst werden könnten.

// This doesn't work. `Scanner` just ignores grouping separators because scanner tends to seek for multiple values
// It just refuses to ignore spaces or commas for example.
let strings = ["en_US": "$9,999.99", "fr_FR": "9999,99€", "de_DE": "9999,99€", "en_GB": "£9,999.99" ]
for str in strings {
    let locale = Locale(identifier: str.key)
    let sc = Scanner(string: str.value)
    sc.charactersToBeSkipped = CharacterSet.decimalDigits.inverted.union(CharacterSet(charactersIn: locale.groupingSeparator ?? ""))
    sc.locale = locale
    print("Locale \(locale.identifier) grouping separator: \(locale.groupingSeparator ?? "") . Decimal separator: \(locale.decimalSeparator ?? "")")
    while !(sc.isAtEnd) {
        if let val = sc.scanDouble() {
            print(val)
        }

    }
}
//     sc.scanDouble(representation: Scanner.NumberRepresentation) could help if there were .currency case

Es ist kein Problem, das Gebietsschema automatisch zu erkennen. Beachten Sie, dass groupingSeparator im französischen Gebietsschema in der Zeichenfolge "Mon salaire est 9 999,99 €" kein Leerzeichen ist, obwohl es möglicherweise genau als Leerzeichen gerendert wird (hier nicht). Deshalb funktioniert der folgende Code einwandfrei, ohne dass !$0.isWhitespaceZeichen herausgefiltert werden.

let stringsArr = ["My salary is $9,999.99",
                  "Mon salaire est 9 999,99€",
                  "Mein Gehalt ist 9.999,99€",
                  "My salary is £9,999.99" ]

let tagger = NSLinguisticTagger(tagSchemes: [.language], options: Int(NSLinguisticTagger.Options.init().rawValue))
for str in stringsArr {
    tagger.string = str
    let locale = Locale(identifier: tagger.dominantLanguage ?? "en")
    let valStr = str.filter{!($0 == Character(locale.groupingSeparator ?? ""))}
    print("Value String", valStr)

    let sc = Scanner(string: valStr)
    // we could do this more reliably with `filter` as well
    sc.charactersToBeSkipped = CharacterSet.decimalDigits.inverted
    sc.locale = locale

    print("Locale \(locale.identifier) grouping separator: |\(locale.groupingSeparator ?? "")| . Decimal separator: \(locale.decimalSeparator ?? "")")
    while !(sc.isAtEnd) {
        if let val = sc.scanDouble() {
            print(val)
        }

    }
}
// Also will fail if groupingSeparator == decimalSeparator (but don't think it's possible)
Paul B.
quelle
-1

Ich finde es besser lesbar, String wie folgt eine Erweiterung hinzuzufügen:

extension String {
    var doubleValue: Double {
        return (self as NSString).doubleValue
    }
}

und dann könnten Sie einfach Ihren Code schreiben:

myDouble = myString.doubleValue
Gutty1
quelle
-1

Mein Problem war Komma, also löse ich es so:

extension String {
    var doubleValue: Double {
        return Double((self.replacingOccurrences(of: ",", with: ".") as NSString).doubleValue)
    }
}
Murat Akdeniz
quelle
-3
var stringValue = "55"

var convertToDouble = Double((stringValue as NSString).doubleValue)
Mo Abdulmalik
quelle
-6

Wir können den CDouble-Wert verwenden, der von myString.doubleValue erhalten wird

ANIL.MUNDURU
quelle
Fehler: 'String' hat kein Mitglied namens 'doubleValue'
Matthew Knippen
@ Matthew Ja, es gibt kein Mitglied namens "double value", also können wir CDouble Value
ANIL.MUNDURU verwenden.
1
en.wikipedia.org/wiki/… Beziehen Sie sich dort auf komplexe Zahlen und lesen Sie die Swift-Referenzdokumentation. Es gibt keine CDouble ... Sprechen Sie über Swift oder eine andere Sprache? Und ich meine schnell ohne Erweiterungen?
Adrian Sluyters