Вы должны использовать инициализаторы нового типа для преобразования между строковым и числовым типами (Double, Float, Int). Он возвратит необязательный тип (Double?), Который будет иметь правильное значение или ноль, если строка не была числом.
Примечание. Свойство NSString doubleValue не рекомендуется, поскольку оно возвращает 0, если значение не может быть преобразовано (например, неверный ввод данных пользователем).
let lessPrecisePI =Float("3.14")let morePrecisePI =Double("3.1415926536")let invalidNumber =Float("alphabet")//nil, not a valid number
Разверните значения, чтобы использовать их, используя if / let
iflet cost =Double(textField.text!){
print("The user entered a value price of \(cost)")}else{
print("Not a valid number: \(textField.text!)")}
Вы можете конвертировать отформатированные числа и валюту, используя NumberFormatterкласс.
let formatter =NumberFormatter()
formatter.locale =Locale.current // USA: Locale(identifier: "en_US")formatter.numberStyle =.decimallet number = formatter.number(from:"9,999.99")
Форматы валют
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 Kingdomformatter.numberStyle =.currency
formatter.locale = usLocalelet usCurrency = formatter.number(from:"$9,999.99")
formatter.locale = frenchLocalelet 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 = germanLocalelet germanCurrency = formatter.number(from:"9999,99€")// Note: "9.999,99€" fails with grouping separator
formatter.locale = englishUKLocalelet englishUKCurrency = formatter.number(from:"£9,999.99")
Другая проблема заключается в том, что он не поддерживает числа в других локалях, кроме 1000,00, если вы используете другие форматы, например 1 000,00, в конце будет обрезано 2 знака после запятой. По крайней мере, так происходит в Objective-C. - В соответствии с документацией Apple: (они не учитывают языковой стандарт). Все следующие удобные методы пропускают начальные пробельные символы (whitespaceSet) и игнорируют завершающие символы. Они не осведомлены о локали. NSScanner или NSNumberFormatter могут использоваться для более мощного и ориентированного на локали анализа чисел.
MSCW
@mskw Я добавил дополнительные сведения об использовании NumberFormatter для анализа валюты. В моем коде я соберу воедино несколько попыток форматирования, используя синтаксис if / let, чтобы я мог анализировать как числа в формате валюты ($ 1,000.00), так и числа в формате (1,000). Вы не всегда знаете, как пользователь будет вводить числа, поэтому возможность поддерживать оба варианта идеальна для группы операторов if / let.
Пол Солт
276
Обновление Swift 2
Появились новые неисправные инициализаторы, которые позволяют вам делать это более идиоматичным и безопасным способом (как отмечалось во многих ответах, двойное значение NSString не очень безопасно, поскольку оно возвращает 0 для нечисловых значений. Это означает, что doubleValueof "foo"и "0"являются тот же самый.)
let myDouble =Double(myString)
Это возвращает необязательный параметр, поэтому в случаях, когда передается, "foo"где doubleValueбы возвратил 0, возвращается неисправный инициализатор nil. Вы можете использовать guard, if-letили mapдля обрабатыватьOptional<Double>
Исходное сообщение:
Вам не нужно использовать конструктор NSString, как предлагает принятый ответ. Вы можете просто соединить это так:
Охай, Ярсен. Недостатком этого подхода является то, что он не потерпит неудачу, если строка не является допустимым двойным числом. Вместо этого вы просто получите 0.0. То есть результат - [NSString doubleValue]является Doubleбыстрым по сравнению с Double?( Optional<Double>). Это отличается от функции Swift String, toInt()которая возвращает Int?и указывает в документах, что она "... принимает строки, соответствующие регулярному выражению" [- +]? [0-9] + "only". "
Деррик Хэтэуэй
Да, использование .toInt()будет лучше. Однако это был скорее ответ на вопрос, как сделать то же самое, но в Swift.
Ярсен
Этот подход тесно связывает вас с Foundation и, скорее всего, не будет работать ни с какими реализациями Swift, не принадлежащими Apple.
Эрик Кербер
5
В Swift 2.0 Double.init?(_ text: String)теперь доступен сбойный инициализатор.
миксель
3
Это не лучший подход. Это не удастся в зависимости от десятичного разделителя. Это будет хорошо с '.' но не с ','. NSNumberFormatter будет поддерживать десятичный разделитель, используемый в текущей локализации.
Джулиан Крол
75
Для немного большего ощущения Swift, использование NSFormatter()избегает приведения NSStringи возвращает, nilкогда строка не содержит Doubleзначения (например, «test» не вернется 0.0).
let double =NSNumberFormatter().numberFromString(myString)?.doubleValue
В качестве альтернативы, расширение Stringтипа Swift :
Мне нравится идея расширения класса String для приложений, которые будут использовать конвертацию в нескольких местах. Но я не вижу выгоды от сложности вызова NSNumberFormatter, поскольку приведение к NSString и использование .doubleValue, по-видимому, по крайней мере так же прямое, и их легче читать и запоминать.
ясно,
12
На самом деле преимущество использования NSNumberFormatter () состоит в том, что numberFromString: метод вернет nil, если строка содержит символы, которые не составляют двойное число. Проблема с doubleValue на NSString заключается в том, что он всегда будет возвращать значение double (например, 0.0 для «test») независимо. Поэтому, если вы имеете дело со всеми видами строк и хотите проверить, является ли строка просто двойной, без дополнительных символов, используйте NSNumberFormatter.
Диркгротен
4
Это терпит неудачу на французском языке.
Питер К.
1
Это отличное решение, но, используя только этот код, оно не будет работать в тех странах, где в качестве разделителей используются запятые (включая Францию как @PeterK. Упоминается). Я попытался написать комментарий с решением, но это было слишком долго, поэтому мне пришлось вместо этого сделать ответ. Вот и вы: Модифицированное решение
Джейкоб Р
53
Другой вариант здесь - преобразовать это в NSStringи использовать это:
let string =NSString(string: mySwiftString)
string.doubleValue
Я бы хотел, чтобы был лучший способ сделать это. Как я могу узнать, если разбор не удался, например.
Райан Хоффман
2
@RyanHoffman К сожалению, в контракте NSString doubleValue этого никогда не было. Все, что вы получите, это 0.0, если строка не начинается с правильного представления числа, HUGE_VAL и -HUGE_VAL при переполнении / потоке. Если вы хотите узнать, почему не удалось выполнить синтаксический анализ, я считаю, что вам нужно взглянуть на NSNumberFormatter, который был разработан для более надежной обработки преобразования чисел и строк.
Ярсен
Так как может быть трудно найти этот ответ, вот он:(swiftString as NSString).doubleValue
LearnCocos2D
24
Вот метод расширения, который позволяет вам просто вызвать doubleValue () для строки Swift и получить двойной возврат (пример вывода идет первым)
extensionString{func doubleValue()->Double{let minusAscii:UInt8=45let dotAscii:UInt8=46let zeroAscii:UInt8=48var res =0.0let ascii =self.utf8var 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=1forvar 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
}}
Нет проверки ошибок, но вы можете добавить его, если вам это нужно.
Double.init?(_ text: String)стать доступным в Swift 2.0. Вы должны упомянуть это. Другие ответы здесь не потому, что люди думают как разработчики Objective-C, а потому, что этот инициализатор не был доступен ранее.
миксель
Действительно, ты прав. Это доступно только в Swift 2.0, я упомяну об этом :) Но, как и в других языках, вы инициализируете тип с другим и не должны ожидать, что тип сможет конвертировать в другой. Долгие дебаты, но, как разработчик Obj-C, у меня много плохих практик при программировании со Swift, и это одна из них :)
Примечание: - Если строка содержит какие-либо символы, кроме числовых цифр или соответствующей группе локали или десятичного разделителя, синтаксический анализ завершится неудачно. - Любые символы начального или конечного пробела в строке игнорируются. Например, строки «5», «5» и «5» дают число 5.
Я не видел ответа, который искал. Я просто отправлю сюда свои сообщения на случай, если это кому-нибудь поможет. Этот ответ действителен, только если вам не нужен определенный формат .
bridgeToObjectiveC () был удален в Xcode 6 Beta 5. Метод мистера Смайли - самый быстрый, который я нашел на данный момент
faraquet99
7
Это основано на ответе @Ryu
Его решение великолепно, если вы находитесь в стране, где точки используются в качестве разделителей. По умолчанию NSNumberFormatterиспользуется локаль устройства. Поэтому это не удастся во всех странах, где запятая используется в качестве разделителя по умолчанию (включая Францию как @PeterK. Упомянуто), если число использует точки в качестве разделителей (что обычно имеет место). Чтобы установить локаль этого NSNumberFormatter в US и, таким образом, использовать точки в качестве разделителей, заменить строку
Который будет выполнять кастинг для вас. Если Apple добавит doubleValueстроку к нативной строке, вам просто нужно удалить расширение, а остальная часть вашего кода будет автоматически скомпилирована!
Метод Apple будет называться .toDouble ... так же, как toInt. Это странное упущение. Вероятно, будет исправлено в будущей версии Swift. Мне больше нравится метод расширения, он сохраняет код в чистоте.
n13
Возвращаемое значение должно быть Double NOT a Float
Leo Dabus
4
SWIFT 3
Чтобы очистить, в настоящее время есть метод по умолчанию:
public init?(_ text: String)из Doubleкласса.
Может использоваться для всех классов.
let c = Double("-1.0")let f = Double("0x1c.6")let i = Double("inf") , и т.д.
// 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.
Использование Scannerв некоторых случаях очень удобный способ извлечения чисел из строки. И он почти такой же мощный, как NumberFormatterи в случае декодирования и работы с различными числовыми форматами и локалями. Он может извлекать числа и валюты с различными десятичными и групповыми разделителями.
importFoundation// 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){iflet val = sc.scanDouble(){
print(val)}}}
Однако существуют проблемы с разделителями, которые можно рассматривать как разделители слов.
// 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){iflet val = sc.scanDouble(){
print(val)}}}// sc.scanDouble(representation:Scanner.NumberRepresentation) could help if there were .currency case
Нет проблем с автоматическим определением локали. Обратите внимание, что groupingSeparator во французском языке в строке «Mon salaire est 9 999,99 €» не является пробелом, хотя может отображаться точно как пробел (здесь это не так). Вот почему приведенный ниже код прекрасно работает без !$0.isWhitespaceфильтрации символов.
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){iflet val = sc.scanDouble(){
print(val)}}}//Also will fail if groupingSeparator == decimalSeparator (but don't think it's possible)
Ошибка: у «String» нет члена с именем «doubleValue»
Мэтью Книппен
@ Matthew Да, нет члена с именем "double value", поэтому мы можем использовать CDouble Value
ANIL.MUNDURU
1
ru.wikipedia.org/wiki/… Ссылайтесь на комплексные числа и читайте справочную документацию Swift. Там нет CDouble ... Вы говорите о Swift или другом языке? А я имею ввиду swift без расширений?
Ответы:
Swift 4.2+ Строка, чтобы удвоить
Вы должны использовать инициализаторы нового типа для преобразования между строковым и числовым типами (Double, Float, Int). Он возвратит необязательный тип (Double?), Который будет иметь правильное значение или ноль, если строка не была числом.
Примечание. Свойство NSString doubleValue не рекомендуется, поскольку оно возвращает 0, если значение не может быть преобразовано (например, неверный ввод данных пользователем).
Разверните значения, чтобы использовать их, используя if / let
Вы можете конвертировать отформатированные числа и валюту, используя
NumberFormatter
класс.Форматы валют
Читайте больше на моем блоге о преобразовании типа String в Double (и валюту) .
источник
Обновление Swift 2 Появились новые неисправные инициализаторы, которые позволяют вам делать это более идиоматичным и безопасным способом (как отмечалось во многих ответах, двойное значение NSString не очень безопасно, поскольку оно возвращает 0 для нечисловых значений. Это означает, что
doubleValue
of"foo"
и"0"
являются тот же самый.)Это возвращает необязательный параметр, поэтому в случаях, когда передается,
"foo"
гдеdoubleValue
бы возвратил 0, возвращается неисправный инициализаторnil
. Вы можете использоватьguard
,if-let
илиmap
для обрабатыватьOptional<Double>
Исходное сообщение: Вам не нужно использовать конструктор NSString, как предлагает принятый ответ. Вы можете просто соединить это так:
источник
- [NSString doubleValue]
являетсяDouble
быстрым по сравнению сDouble?
(Optional<Double>
). Это отличается от функции Swift String,toInt()
которая возвращаетInt?
и указывает в документах, что она "... принимает строки, соответствующие регулярному выражению" [- +]? [0-9] + "only". ".toInt()
будет лучше. Однако это был скорее ответ на вопрос, как сделать то же самое, но в Swift.Double.init?(_ text: String)
теперь доступен сбойный инициализатор.Для немного большего ощущения Swift, использование
NSFormatter()
избегает приведенияNSString
и возвращает,nil
когда строка не содержитDouble
значения (например, «test» не вернется0.0
).В качестве альтернативы, расширение
String
типа Swift :и используйте это как
toInt()
:Это возвращает необязательный,
Double?
который должен быть развернут.Либо с принудительной распаковкой:
или с оператором if let:
Обновление: для локализации очень легко применить локали к NSFormatter следующим образом:
Наконец, вы можете использовать
NSNumberFormatterCurrencyStyle
в форматере, если вы работаете с валютами, где строка содержит символ валюты.источник
Другой вариант здесь - преобразовать это в
NSString
и использовать это:источник
(swiftString as NSString).doubleValue
Вот метод расширения, который позволяет вам просто вызвать doubleValue () для строки Swift и получить двойной возврат (пример вывода идет первым)
Вот метод расширения:
Нет проверки ошибок, но вы можете добавить его, если вам это нужно.
источник
Начиная с Swift 1.1, вы можете напрямую перейти
String
кconst char *
параметру.Если вам не нравится устаревший
atof
:Одно предостережение: поведение конверсии отличается от
NSString.doubleValue
.atof
иstrtod
принять0x
префиксную шестнадцатеричную строку:Если вы предпочитаете
.doubleValue
поведение, мы все равно можем использоватьCFString
мостовое соединение:источник
NSString
.В Swift 2.0 лучший способ - избегать думать как разработчик Objective-C. Таким образом, вы не должны «преобразовывать строку в двойную», но вы должны «инициализировать двойную строку». Apple документ здесь: https://developer.apple.com/library/ios//documentation/Swift/Reference/Swift_Double_Structure/index.html#//apple_ref/swift/structctr/Double/s:FSdcFMSdFSSGSqSd_
Это необязательный init, поэтому вы можете использовать оператор объединения nil (??) для установки значения по умолчанию. Пример:
источник
Double.init?(_ text: String)
стать доступным в Swift 2.0. Вы должны упомянуть это. Другие ответы здесь не потому, что люди думают как разработчики Objective-C, а потому, что этот инициализатор не был доступен ранее.На SWIFT 3 вы можете использовать:
Примечание: - Если строка содержит какие-либо символы, кроме числовых цифр или соответствующей группе локали или десятичного разделителя, синтаксический анализ завершится неудачно. - Любые символы начального или конечного пробела в строке игнорируются. Например, строки «5», «5» и «5» дают число 5.
Взято из документации: https://developer.apple.com/reference/foundation/numberformatter/1408845-number
источник
Я не видел ответа, который искал. Я просто отправлю сюда свои сообщения на случай, если это кому-нибудь поможет. Этот ответ действителен, только если вам не нужен определенный формат .
Свифт 3
источник
Попробуй это:
НОТА
Удалено в бета-версии 5. Это больше не работает?
источник
Это основано на ответе @Ryu
Его решение великолепно, если вы находитесь в стране, где точки используются в качестве разделителей. По умолчанию
NSNumberFormatter
используется локаль устройства. Поэтому это не удастся во всех странах, где запятая используется в качестве разделителя по умолчанию (включая Францию как @PeterK. Упомянуто), если число использует точки в качестве разделителей (что обычно имеет место). Чтобы установить локаль этого NSNumberFormatter в US и, таким образом, использовать точки в качестве разделителей, заменить строкус участием
Поэтому полный код становится
Чтобы использовать это, просто позвоните
"Your text goes here".toDouble()
Это вернет дополнительный
Double?
Как упомянул @Ryu, вы можете принудительно развернуть:
или используйте
if let
утверждение:источник
NumberFormatter().number(from: myString)?.doubleValue
SWIFT 4
источник
Swift 4.0
попробуй это
источник
Свифт: 4 и 5
Есть два способа сделать это:
String -> Int -> Double:
String -> NSString -> Double
Используйте его так, как вам нравится, в соответствии с вашими требованиями.
источник
Пожалуйста, проверьте это на детской площадке!
Кстати в моем Xcode
.toDouble () - не существует
.doubleValue создать значение 0.0 из нечисловых строк ...
источник
1.
2.
Может быть, это поможет вам.
источник
Как уже указывалось, лучший способ добиться этого с помощью прямого литья:
Основываясь на этом, вы можете сделать отличное расширение Swift String:
Это позволяет напрямую использовать:
Который будет выполнять кастинг для вас. Если Apple добавит
doubleValue
строку к нативной строке, вам просто нужно удалить расширение, а остальная часть вашего кода будет автоматически скомпилирована!источник
SWIFT 3
Чтобы очистить, в настоящее время есть метод по умолчанию:
public init?(_ text: String)
изDouble
класса.Может использоваться для всех классов.
let c = Double("-1.0")
let f = Double("0x1c.6")
let i = Double("inf")
, и т.д.источник
Расширение с дополнительным языковым стандартом
Swift 2.2
Swift 3.1
источник
Или вы могли бы сделать:
источник
Вы можете использовать StringEx . Он распространяется
String
с преобразованиями строк в числа, включаяtoDouble()
.Он проверяет строку и завершается ошибкой, если ее нельзя преобразовать в double.
Пример:
источник
Swift 4
источник
Что также работает:
источник
Используйте этот код в Swift 2.0
let strWithFloat = "78.65" let floatFromString = Double(strWithFloat)
источник
Использование
Scanner
в некоторых случаях очень удобный способ извлечения чисел из строки. И он почти такой же мощный, какNumberFormatter
и в случае декодирования и работы с различными числовыми форматами и локалями. Он может извлекать числа и валюты с различными десятичными и групповыми разделителями.Однако существуют проблемы с разделителями, которые можно рассматривать как разделители слов.
Нет проблем с автоматическим определением локали. Обратите внимание, что groupingSeparator во французском языке в строке «Mon salaire est 9 999,99 €» не является пробелом, хотя может отображаться точно как пробел (здесь это не так). Вот почему приведенный ниже код прекрасно работает без
!$0.isWhitespace
фильтрации символов.источник
Я считаю более читабельным добавить расширение для String следующим образом:
и тогда вы просто можете написать свой код:
источник
моя проблема была запятая, поэтому я решаю ее так:
источник
источник
мы можем использовать значение CDouble, которое будет получено myString.doubleValue
источник