Я пытаюсь написать программу BMI на быстром языке. И у меня возникла эта проблема: как преобразовать строку в двойную?
В Objective-C я могу сделать вот так:
double myDouble = [myString doubleValue];
Но как я могу добиться этого на языке Swift?
Я пытаюсь написать программу BMI на быстром языке. И у меня возникла эта проблема: как преобразовать строку в двойную?
В Objective-C я могу сделать вот так:
double myDouble = [myString doubleValue];
Но как я могу добиться этого на языке Swift?
Swift 4. 2+ Строка для удвоения
Вы должны использовать инициализаторы нового типа для преобразования между строковым и числовым типами (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
if let 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 = .decimal
let 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 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")
Читайте больше в моем блоге о преобразовании типа String в Double (и валюту).
Обновление Swift 2
Существуют новые отказоустойчивые инициализаторы, которые позволяют вам делать это более идиоматичным и безопасным способом (как было отмечено многими ответами, двойное значение NSString не очень безопасно, потому что оно возвращает 0 для значений без номера. Это означает, что doubleValue
of "foo"
и "0"
совпадают.)
let myDouble = Double(myString)
Возвращает необязательный параметр, поэтому в случаях, когда передача "foo"
, где doubleValue
вернула бы 0, возвращаемый intializer вернет nil
. Вы можете использовать guard
, if-let
или map
для обработки Optional<Double>
Оригинальное сообщение: Вам не нужно использовать конструктор NSString, как предлагает принятый ответ. Вы можете просто провести его так:
(swiftString as NSString).doubleValue
Для немного более быстрого ощущения, используя NSFormatter()
, избегает кастинга до NSString
и возвращает nil
, когда строка не содержит значения Double
(например, "test" не вернет 0.0
).
let double = NSNumberFormatter().numberFromString(myString)?.doubleValue
В качестве альтернативы, расширение типа Swift String
:
extension String {
func toDouble() -> Double? {
return NSNumberFormatter().numberFromString(self)?.doubleValue
}
}
и используйте его как toInt()
:
var myString = "4.2"
var myDouble = myString.toDouble()
Это возвращает необязательный Double?
, который необходимо развернуть.
Либо с принудительной разворачиванием:
println("The value is \(myDouble!)") // prints: The value is 4.2
или с выражением if let:
if let myDouble = myDouble {
println("The value is \(myDouble)") // prints: The value is 4.2
}
Update: Для локализации очень легко применять локали к NSFormatter следующим образом:
let formatter = NSNumberFormatter()
formatter.locale = NSLocale(localeIdentifier: "fr_FR")
let double = formatter.numberFromString("100,25")
Наконец, вы можете использовать NSNumberFormatterCurrencyStyle
в форматировании, если работаете с валютами, где строка содержит символ валюты.
Другим вариантом здесь является преобразование этого в NSString
и использование этого:
let string = NSString(string: mySwiftString)
string.doubleValue
Здесь используется метод расширения, который позволяет вам просто вызвать doubleValue() в строке Swift и получить двойную обратную сторону (сначала выводится вывод)
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
Здесь метод расширения:
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
}
}
Нет проверки ошибок, но вы можете добавить его, если вам это нужно.
С Swift 1.1 вы можете напрямую передать параметр String
в const char *
.
import Foundation
let str = "123.4567"
let num = atof(str) // -> 123.4567
atof("123.4567fubar") // -> 123.4567
Если вам не нравится устаревший atof
:
strtod("765.4321", nil) // -> 765.4321
Одно предостережение: поведение преобразования отличается от NSString.doubleValue
.
atof
и strtod
принять 0x
префиксную шестнадцатеричную строку:
atof("0xffp-2") // -> 63.75
atof("12.3456e+2") // -> 1,234.56
atof("nan") // -> (not a number)
atof("inf") // -> (+infinity)
Если вы предпочитаете поведение .doubleValue
, мы все равно можем использовать мост CFString
:
let str = "0xff"
atof(str) // -> 255.0
strtod(str, nil) // -> 255.0
CFStringGetDoubleValue(str) // -> 0.0
(str as NSString).doubleValue // -> 0.0
В Swift 2.0 лучший способ - не думать о разработчике Objective-C. Таким образом, вы не должны "преобразовывать строку в двойную", но вам следует "инициализировать Double from the String". Apple doc здесь: https://developer.apple.com/library/ios//documentation/Swift/Reference/Swift_Double_Structure/index.html#//apple_ref/swift/structctr/Double/s:FSdcFMSdFSSGSqSd_
Это необязательный init, поэтому вы можете использовать оператор объединения nil (??) для установки значения по умолчанию. Пример:
let myDouble = Double("1.1") ?? 0.0
Попробуйте следующее:
var myDouble = myString.bridgeToObjectiveC().doubleValue
println(myDouble)
Примечание
Удалено в бета-версии 5. Это больше не работает?
В SWIFT 3 вы можете использовать:
if let myDouble = NumberFormatter().number(from: yourString)?.doubleValue {
print("My double: \(myDouble)")
}
Примечание: - Если строка содержит любые символы, отличные от числовых цифр или соответствующие группе или десятичные разделители, синтаксический анализ завершится с ошибкой. - Любые символы разделителя пробелов или строк в строке игнорируются. Например, строки "5" , "5" и "5" производят номер 5.
Взято из документации: https://developer.apple.com/reference/foundation/numberformatter/1408845-number
Я не видел ответа, который искал. Я просто отправляю сюда свои сообщения на случай, если это кому-нибудь поможет. Этот ответ действителен, только если вам не нужен определенный формат.
Свифт 3
extension String {
var toDouble: Double {
return Double(self) ?? 0.0
}
}
Это основано на ответе @Ryu
Его решение велико, пока вы находитесь в стране, где точки используются в качестве разделителей. По умолчанию NSNumberFormatter
использует локали устройств. Поэтому это не удастся во всех странах, где запятая используется как разделитель по умолчанию (в том числе Франция как @PeterK), если число использует точки в качестве разделителей (что обычно бывает). Чтобы установить локаль этого NSNumberFormatter равным US и, таким образом, использовать точки в качестве разделителей, замените строку
return NSNumberFormatter().numberFromString(self)?.doubleValue
с
let numberFormatter = NSNumberFormatter()
numberFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
return numberFormatter.numberFromString(self)?.doubleValue
Поэтому полный код становится
extension String {
func toDouble() -> Double? {
let numberFormatter = NSNumberFormatter()
numberFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
return numberFormatter.numberFromString(self)?.doubleValue
}
}
Чтобы использовать это, просто позвоните "Your text goes here".toDouble()
Это вернет необязательный Double?
Как упоминалось в @Ryu, вы можете либо принудительно развернуть:
println("The value is \(myDouble!)") // prints: The value is 4.2
или используйте оператор if let
:
if let myDouble = myDouble {
println("The value is \(myDouble)") // prints: The value is 4.2
}
Пожалуйста, проверьте это на детской площадке!
let sString = "236.86"
var dNumber = NSNumberFormatter().numberFromString(sString)
var nDouble = dNumber!
var eNumber = Double(nDouble) * 3.7
Кстати, в моем Xcode
.toDouble() - не существует
.doubleValue создает значение 0.0 из не числовых строк...
SWIFT 4
extension String {
func toDouble() -> Double? {
let numberFormatter = NumberFormatter()
numberFormatter.locale = Locale(identifier: "en_US_POSIX")
return numberFormatter.number(from: self)?.doubleValue
}
}
1.
let strswift = "12"
let double = (strswift as NSString).doubleValue
2.
var strswift= "10.6"
var double : Double = NSString(string: strswift).doubleValue
Может быть, эта помощь для вас.
SWIFT 3
Чтобы очистить, в настоящее время существует метод по умолчанию:
public init?(_ text: String)
класса Double
.
Он может использоваться для всех классов.
let c = Double("-1.0")
let f = Double("0x1c.6")
let i = Double("inf")
и т.д.
попробуй это
let str:String = "111.11"
let tempString = (str as NSString).doubleValue
print("String:-",tempString)
Как уже указывалось, лучший способ достичь этого - с прямым литьем:
(myString as NSString).doubleValue
Создавая это, вы можете сделать плавное расширение Swift String:
extension String {
var doubleValue: Double {
return (self as NSString).doubleValue
}
}
Это позволяет вам напрямую использовать:
myString.doubleValue
Который выполнит кастинг для вас. Если Apple добавит doubleValue
к родной String, вам просто нужно удалить расширение, а остальная часть вашего кода будет автоматически компилироваться.
Расширение с дополнительным языковым стандартом
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
}
}
}
Или вы могли бы сделать:
var myDouble = Double((mySwiftString.text as NSString).doubleValue)
Вы можете использовать StringEx. Он расширяет String
с преобразованием строк в число, включая toDouble()
.
extension String {
func toDouble() -> Double?
}
Он проверяет строку и терпит неудачу, если ее нельзя преобразовать в double.
Пример:
import StringEx
let str = "123.45678"
if let num = str.toDouble() {
println("Number: \(num)")
} else {
println("Invalid string")
}
Свифт: - 4
Есть два способа сделать это:
String → Int → Double:
let strNumber = "314"
let intFromString = Int(strNumber)
let dobleFromInt = Double(intFromString!)
print(dobleFromInt)
String → NSString → Double
let strNumber = "314"
let NSstringFromString = NSString(string: strNumber as! NSString)
let doubleFromNSString = NSstringFromString.doubleValue
print(doubleFromNSString)
Используйте его так, как вам нравится, в соответствии с вашими требованиями.
Swift 4
extension String {
func toDouble() -> Double {
let nsString = self as NSString
return nsString.doubleValue
}
}
Что также работает:
// 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.
Используйте этот код в Swift 2.0
let strWithFloat = "78.65"
let floatFromString = Double(strWithFloat)
Я нахожу более читаемым, чтобы добавить расширение к String следующим образом:
extension String {
var doubleValue: Double {
return (self as NSString).doubleValue
}
}
а затем вы можете написать свой код:
myDouble = myString.doubleValue
Моя проблема была запятой, поэтому я решаю ее следующим образом:
extension String {
var doubleValue: Double {
return Double((self.replacingOccurrences(of: ",", with: ".") as NSString).doubleValue)
}
}
var stringValue = "55"
var convertToDouble = Double((stringValue as NSString).doubleValue)
мы можем использовать значение CDouble, которое будет получено myString.doubleValue