Swift - jak przekonwertować ciąg znaków na podwójny

242

Próbuję napisać program BMI w szybkim języku. Mam problem: jak przekonwertować ciąg znaków na podwójne?

W Objective-C mogę zrobić tak:

double myDouble = [myString doubleValue];

Ale jak mogę to osiągnąć w języku Swift?

o tak
źródło
1
Zmieniło się to w Swift 2, zobacz nową odpowiedź przy użyciu nowego inicjalizatora awaryjnego Double (): stackoverflow.com/a/32850058/276626
Paul Solt

Odpowiedzi:

205

Swift 4.2+ String to Double

Powinieneś użyć inicjatorów nowego typu do konwersji między typami String i numerycznymi (Double, Float, Int). Zwróci typ opcjonalny (Double?), Który będzie miał poprawną wartość lub zero, jeśli ciąg nie był liczbą.

Uwaga: Właściwość NSString doubleValue nie jest zalecana, ponieważ zwraca 0, jeśli wartość nie może zostać przekonwertowana (tj. Złe dane wprowadzone przez użytkownika).

let lessPrecisePI = Float("3.14")

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

Rozpakuj wartości, aby użyć ich za pomocą 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!)")
}

Możesz konwertować sformatowane liczby i walutę za pomocą NumberFormatterklasy.

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

Formaty walutowe

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

Przeczytaj więcej na moim blogu o konwertowaniu ciągów znaków na podwójne (i walutę) .

Paul Solt
źródło
2
Innym problemem jest to, że nie obsługuje liczb w różnych ustawieniach narodowych innych niż 1 000,00, jeśli użyjesz innych formatów, takich jak 1 000,00, odetnie 2 cyfry po przecinku na końcu. Przynajmniej tak dzieje się w przypadku Celu C. - Zgodnie z dokumentacją Apple: (Nie są one zgodne z ustawieniami regionalnymi) Poniższe metody wygody pomijają początkowe znaki spacji (whitespaceSet) i ignorują końcowe znaki. Nie są świadomi ustawień regionalnych. NSScanner lub NSNumberFormatter może być wykorzystywany do bardziej wydajnego i opartego na ustawieniach regionalnych analizowania liczb.
mskw
@mskw Dodałem dodatkowe szczegóły dotyczące korzystania z NumberFormatter do analizowania waluty. W moim kodzie połączę ze sobą wiele prób formatowania przy użyciu składni if ​​/ let, aby móc analizować zarówno liczby sformatowane w walucie (1 000,00 USD), jak i liczby sformatowane (1000). Nie zawsze wiesz, jak użytkownik wprowadzi liczby, więc możliwość obsługi obu jest idealna z grupą instrukcji if / let.
Paul Solt
276

Swift 2 Update Są nowe inicjalizatory failable które pozwalają to zrobić w bardziej idiomatyczne i bezpieczny sposób (jak wiele odpowiedzi zauważyli, podwójna wartość NSString nie jest bardzo bezpieczne, ponieważ zwraca 0 dla wartości spoza numerycznych. Oznacza to, że doubleValueod "foo"i "0"są to samo.)

let myDouble = Double(myString)

Zwraca to wartość opcjonalną, więc w przypadkach takich jak przekazywanie w "foo"miejsce, w którym doubleValuezwróciłoby 0, zwracany jest niezawodny intializer nil. Można użyć guard, if-letlub mapdo obsługiOptional<Double>

Oryginalny post: Nie musisz używać konstruktora NSString, jak proponuje zaakceptowana odpowiedź. Możesz po prostu to przełączyć w następujący sposób:

(swiftString as NSString).doubleValue
Jarsen
źródło
5
ohai, Jarsen. Wadą tego podejścia jest to, że nie zawiedzie, jeśli łańcuch nie będzie poprawnym podwójnym. Zamiast tego dostaniesz 0,0. Oznacza to, że wynik - [NSString doubleValue]jest Doubleszybki w zastosowaniu do Double?( Optional<Double>). Różni się to od funkcji Swift String, toInt()która zwraca Int?i stwierdza w dokumentach, że „... akceptuje ciągi pasujące do wyrażenia regularnego„ [- +]? [0-9] + ”tylko.”
Derrick Hathaway,
Tak, używanie .toInt()byłoby lepsze. Była to jednak raczej odpowiedź na to, jak zrobić dokładnie to samo, ale w Swift.
Jarsen
Takie podejście ściśle łączy Cię z Foundation i prawdopodobnie nie będzie działać na żadnych implementacjach Swift innych niż Apple.
Erik Kerber,
5
W Swift 2.0 dostępny jest Double.init?(_ text: String)teraz awaryjny inicjator.
mixel
3
To nie jest najlepsze podejście. Nie powiedzie się w zależności od separatora dziesiętnego. Będzie dobrze z „.” ale nie z „,”. NSNumberFormatter będzie obsługiwał separator dziesiętny używany w bieżącej lokalizacji.
Julian Król
75

Aby uzyskać nieco bardziej szybkie uczucie, użycie NSFormatter()unika rzutowania na NSStringi zwraca, nilgdy ciąg nie zawiera Doublewartości (np. „Test” nie zwróci 0.0).

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

Alternatywnie, rozszerzając Stringtyp Swift :

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

i używaj go w następujący sposób toInt():

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

Zwraca to opcję opcjonalną, Double?którą należy rozpakować.

Albo z wymuszonym rozpakowaniem:

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

lub z instrukcją if let:

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

Aktualizacja: W celu lokalizacji bardzo łatwo jest zastosować ustawienia narodowe do NSFormatter w następujący sposób:

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

Na koniec możesz użyć NSNumberFormatterCurrencyStyleformatyzatora, jeśli pracujesz z walutami, w których łańcuch zawiera symbol waluty.

RyuX51
źródło
Podoba mi się pomysł rozszerzenia klasy String dla aplikacji, które będą korzystać z konwersji w wielu miejscach. Ale nie widzę korzyści ze złożoności wywoływania NSNumberFormatter, ponieważ rzutowanie na NSString i używanie .doubleValue wydaje się co najmniej tak bezpośrednie, łatwiejsze do odczytania i zapamiętania.
wyczyść
12
W rzeczywistości zaletą użycia NSNumberFormatter () jest to, że metoda numberFromString: zwróci zero, jeśli ciąg znaków zawiera znaki, które nie tworzą podwójnej liczby. Problem z doubleValue na NSString polega na tym, że zawsze zwróci double (na przykład 0.0 dla „testu”) niezależnie od tego. Więc jeśli masz do czynienia z wszelkiego rodzaju ciągami znaków i chcesz sprawdzić, czy ciąg znaków jest podwójny, żadnych dodatkowych znaków, skorzystaj z NSNumberFormatter.
dirkgroten
4
Nie udaje się to po francusku.
Peter K.,
1
To świetne rozwiązanie, ale użycie tylko tego kodu nie będzie działać w krajach, w których przecinki są używane jako separatory (w tym Francja jako @PeterK. Wspomniane). Próbowałem napisać komentarz z rozwiązaniem, ale było to zbyt długo, więc zamiast tego musiałem udzielić odpowiedzi. Proszę bardzo: zmodyfikowane rozwiązanie
Jacob R
53

Inną opcją jest przekonwertowanie tego na NSStringi użycie tego:

let string = NSString(string: mySwiftString)
string.doubleValue
Keith Smiley
źródło
13
Chciałbym, żeby był to lepszy sposób. Skąd mam wiedzieć, na przykład, czy parsowanie się nie powiodło?
Ryan Hoffman
2
@RyanHoffman Niestety, umowa o podwójnej wartości NSString nigdy tego nie zapewniła. Otrzymasz tylko 0,0, jeśli ciąg nie rozpocznie się od prawidłowej reprezentacji liczby, OGROMNEJ_WARUNKU i -WIELKIEJ_WALNOŚCI w przypadku przepełnienia / niedopełnienia. Jeśli chcesz wiedzieć, dlaczego parsowanie nie powiodło się, uważam, że musisz przyjrzeć się NSNumberFormatter, który został zaprojektowany do obsługi konwersji liczb / ciągów w bardziej niezawodny sposób.
Jarsen
Ponieważ znalezienie tej odpowiedzi może być trudne, oto ona:(swiftString as NSString).doubleValue
LearnCocos2D,
24

Oto metoda rozszerzenia, która pozwala po prostu wywołać doubleValue () na łańcuchu Swift i uzyskać podwójne odwrócenie (przykładowe wyjście jest pierwsze)

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

Oto metoda rozszerzenia:

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

Brak sprawdzania błędów, ale możesz go dodać, jeśli potrzebujesz.

Millie Smith
źródło
20

Począwszy od wersji Swift 1.1, można bezpośrednio przejść Stringdo const char *parametru.

import Foundation

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

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

Jeśli nie lubisz przestarzałych atof:

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

Jedno zastrzeżenie: zachowanie konwersji jest inne niż NSString.doubleValue.

atofi strtodzaakceptuj 0xpoprzedzony ciąg szesnastkowy:

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

Jeśli wolisz .doubleValuezachowanie, nadal możemy korzystać z CFStringmostkowania:

let str = "0xff"
atof(str)                      // -> 255.0
strtod(str, nil)               // -> 255.0
CFStringGetDoubleValue(str)    // -> 0.0
(str as NSString).doubleValue  // -> 0.0
rintaro
źródło
Jestem fanem tego podejścia zamiast castingu do NSString.
Sam Soffes
10

W Swift 2.0 najlepszym sposobem jest unikanie myślenia jak programista Objective-C. Dlatego nie powinieneś „konwertować ciągu na podwójny”, ale „inicjować podwójny z ciągu”. Dokument Apple tutaj: https://developer.apple.com/library/ios//documentation/Swift/Reference/Swift_Double_Structure/index.html#//apple_ref/swift/structctr/Double/s:FSdcFMSdFSSGSqSd_

Jest to opcjonalny init, więc możesz użyć zerowego operatora koalescencyjnego (??), aby ustawić wartość domyślną. Przykład:

let myDouble = Double("1.1") ?? 0.0
Toom
źródło
Double.init?(_ text: String)stają się dostępne w Swift 2.0. Powinieneś o tym wspomnieć. Inne odpowiedzi tutaj nie są dlatego, że ludzie myślą jak programiści Objective-C, ale dlatego, że ten inicjator nie był wcześniej dostępny.
mixel
Rzeczywiście masz rację. Jest to dostępne tylko w Swift 2.0, wspomnę o tym :) Ale podobnie jak w innych językach inicjujesz typ z innym i nie powinieneś oczekiwać, że typ będzie w stanie przekonwertować na inny. Długa debata, ale jako programista Obj-C mam wiele złych praktyk podczas kodowania za pomocą Swift i to jest jedna z nich :)
Toom
10

W SWIFT 3 możesz użyć:

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

Uwaga: - Jeśli ciąg znaków zawiera znaki inne niż cyfry lub separatory grupy lub liczby dziesiętne odpowiednie dla danego regionu, analiza nie powiedzie się. - Wszelkie początkowe lub końcowe znaki separatora spacji w ciągu są ignorowane. Na przykład ciągi „5”, „5” i „5” dają liczbę 5.

Zaczerpnięte z dokumentacji: https://developer.apple.com/reference/foundation/numberformatter/1408845-number

Jorge Luis Jiménez
źródło
10

Nie widziałem odpowiedzi, której szukałem. Po prostu zamieszczam tutaj moje, na wypadek, gdyby to mogło pomóc każdemu. Ta odpowiedź jest ważna tylko wtedy, gdy nie potrzebujesz określonego formatu .

Szybki 3

extension String {
    var toDouble: Double {
        return Double(self) ?? 0.0
    }
}
TomCobo
źródło
9

Spróbuj tego:

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

UWAGA

Usunięto w wersji Beta 5. To już nie działa?

CW0007007
źródło
1
bridgeToObjectiveC () został usunięty w Xcode 6 Beta 5. Metoda pana Smileya jest najszybsza, jaką w tej chwili
znalazłem
7

Opiera się to na odpowiedzi @Ryu

Jego rozwiązanie jest świetne, dopóki jesteś w kraju, w którym kropki są używane jako separatory. Domyślnie NSNumberFormatterużywa ustawień regionalnych urządzeń. Dlatego nie powiedzie się to we wszystkich krajach, w których przecinek jest używany jako domyślny separator (w tym Francja, jak wspomniano @PeterK.), Jeśli liczba używa kropek jako separatorów (co zwykle ma miejsce). Aby ustawić ustawienia regionalne tego NSNumberFormatter na US, a zatem użyj kropek, ponieważ separatory zastępują linię

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

z

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

Dlatego pełny kod staje się

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

Aby z tego skorzystać, wystarczy zadzwonić "Your text goes here".toDouble()

Zwróci to opcjonalne Double?

Jak wspomniano w @Ryu, możesz albo wymusić rozpakowanie:

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

lub użyj if letoświadczenia:

if let myDouble = myDouble {
    println("The value is \(myDouble)") // prints: The value is 4.2
}
Jacob R.
źródło
1
To jest właściwa odpowiedź. Wersja Swift 3 będzie NumberFormatter().number(from: myString)?.doubleValue
Nicolas 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
źródło
6

Swift 4.0

Spróbuj tego

 let str:String = "111.11"
 let tempString = (str as NSString).doubleValue
 print("String:-",tempString)
Vishal Vaghasiya
źródło
6

Szybki: 4 i 5

Można to zrobić na dwa sposoby:

  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)

Używaj go w dowolny sposób, zgodnie z potrzebą kodu.

Abhirajsinh Thakore
źródło
Pierwsza metoda nie działa dla mnie, jednak druga działa całkiem dobrze.
Saurabh
@Saurabh, Czy możesz rozwinąć więcej informacji na temat tego, jaki był twój ciąg znaków?
Abhirajsinh Thakore
5

Sprawdź to na placu zabaw!

let sString = "236.86"

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

Przy okazji w moim Xcode

.toDouble () - nie istnieje

.doubleValue tworzy wartość 0.0 z ciągów nienumerycznych ...

Mamazur
źródło
4

1.

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

2)

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

Może ci to pomóc.

Daxesh Nagar
źródło
4

Jak już wspomniano, najlepszym sposobem na osiągnięcie tego jest rzutowanie bezpośrednie:

(myString as NSString).doubleValue

Opierając się na tym, możesz stworzyć eleganckie natywne rozszerzenie Swift String:

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

Pozwala to na bezpośrednie użycie:

myString.doubleValue

Który wykona dla ciebie casting. Jeśli Apple doda doubleValuenatywny ciąg, wystarczy usunąć rozszerzenie, a reszta kodu automatycznie się skompiluje!

Firo
źródło
Metoda Apple'a zostanie nazwana .toDouble ... tak samo jak toInt. To dziwne pominięcie. Prawdopodobnie zostanie naprawiony w przyszłej wersji Swift. Najbardziej podoba mi się metoda rozszerzenia, utrzymanie kodu w czystości.
n13
Zwrócona
4

SWIFT 3

Aby wyczyścić, obecnie istnieje domyślna metoda:

public init?(_ text: String)z Doubleklasą.

Może być stosowany do wszystkich klas.

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

Wiaczesław
źródło
2

Rozszerzenie z opcjonalnymi ustawieniami narodowymi

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
źródło
1
Dodałem przykład Swift 3.1. Co rozumiesz przez „... i dodaj przykład dla ustawień regionalnych”? 🙂
imike
1

Lub możesz zrobić:

var myDouble = Double((mySwiftString.text as NSString).doubleValue)
jr00n
źródło
1

Możesz użyć StringEx . Rozciąga Stringsię na konwersje ciągów na liczby, w tym toDouble().

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

Sprawdza ciąg i kończy się niepowodzeniem, jeśli nie można go przekonwertować na podwójny.

Przykład:

import StringEx

let str = "123.45678"
if let num = str.toDouble() {
    println("Number: \(num)")
} else {
    println("Invalid string")
}
Staś
źródło
1

Szybki 4

extension String {
    func toDouble() -> Double {
        let nsString = self as NSString
        return nsString.doubleValue
    }
}
Aitor Lucas
źródło
0

Co również działa:

// 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
źródło
UWAGA: „scanDouble” jest przestarzałe w iOS 13.0
uplearnedu.com
0

Użyj tego kodu w Swift 2.0

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

Maninderjit Singh
źródło
0

Używanie Scannerw niektórych przypadkach jest bardzo wygodnym sposobem wydobywania liczb z łańcucha. I jest prawie tak potężny, jak w NumberFormatterprzypadku dekodowania i radzenia sobie z różnymi formatami liczb i lokalizacjami. Może wyodrębniać liczby i waluty z różnymi separatorami dziesiętnymi i grupowymi.

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

    }
}

Istnieją jednak problemy z separatorami, które można by traktować jako ograniczniki słów.

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

Nie ma problemu z automatycznym wykryciem ustawień regionalnych. Zauważ, że groupingSeparator w języku francuskim w łańcuchu „Mon salaire est 9 999,99 €” nie jest spacją, chociaż może renderować się dokładnie jako spacja (tutaj nie ma). Właśnie dlatego poniższy kod działa dobrze bez !$0.isWhitespaceodfiltrowywania znaków.

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.
źródło
-1

Bardziej czytelne wydaje się dodanie rozszerzenia do ciągu w następujący sposób:

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

i wtedy możesz po prostu napisać kod:

myDouble = myString.doubleValue
Gutty1
źródło
-1

moim problemem był przecinek, więc rozwiązałem go w ten sposób:

extension String {
    var doubleValue: Double {
        return Double((self.replacingOccurrences(of: ",", with: ".") as NSString).doubleValue)
    }
}
Murat Akdeniz
źródło
-3
var stringValue = "55"

var convertToDouble = Double((stringValue as NSString).doubleValue)
Mo Abdulmalik
źródło
-6

możemy użyć wartości CDouble, która zostanie uzyskana przez myString.doubleValue

ANIL.MUNDURU
źródło
Błąd: ciąg „String” nie ma elementu o nazwie „doubleValue”
Matthew Knippen,
@Matthew Tak, nie ma członka o nazwie „podwójna wartość”, więc możemy użyć CDouble Value
ANIL.MUNDURU
1
en.wikipedia.org/wiki/... Odwołaj się do liczb zespolonych i przeczytaj dokumentację referencyjną Swift. Nie ma CDp2 ... Czy mówisz o Swift lub innym języku? Mam na myśli szybkie bez rozszerzeń?
Adrian Sluyters,