Преобразование строки в плавающую в Swift


101

Я пытаюсь преобразовать числа, взятые из UITextField, которые, как я полагаю, на самом деле являются строками, и преобразовать их в Float, чтобы я мог их умножать.

У меня есть два UITextfields, которые объявлены следующим образом:

@IBOutlet var wage: UITextField
@IBOutlet var hour: UITextField

Когда пользователь нажимает кнопку UIButton, я хочу вычислить заработную плату, которую получает пользователь, но не могу, так как мне нужно сначала преобразовать их в числа с плавающей запятой, прежде чем я смогу их использовать.

Я знаю, как преобразовать их в целое число, выполнив следующие действия:

var wageConversion:Int = 0
wageConversion = wage.text.toInt()!

Однако я понятия не имею, как преобразовать их в числа с плавающей запятой.

Ответы:


200

Swift 2.0+

Теперь с Swift 2.0 вы можете просто использовать, Float(Wage.text)который возвращает Float?тип. Более ясное, чем приведенное ниже решение, которое только что возвращается 0.

Если по какой-то причине вам нужно 0значение для недействительного, Floatвы можете использовать значение, Float(Wage.text) ?? 0которое вернется, 0если оно недействительно Float.


Старое решение

Лучший способ справиться с этим - прямое приведение:

var WageConversion = (Wage.text as NSString).floatValue

Я на самом деле создал, extensionчтобы лучше использовать это:

extension String {
    var floatValue: Float {
        return (self as NSString).floatValue
    }
}

Теперь вы можете просто позвонить var WageConversion = Wage.text.floatValueи разрешить добавочному номеру управлять мостом за вас!

Это хорошая реализация, поскольку она может обрабатывать фактические числа с плавающей запятой (ввод с помощью .), а также поможет предотвратить копирование пользователем текста в поле ввода ( 12p.34или даже 12.12.41).

Очевидно, что если Apple добавит floatValueв Swift, это вызовет исключение, но в то же время это может быть неплохо. Если они добавят его позже, то все, что вам нужно сделать для изменения кода, - это удалить расширение, и все будет работать без проблем, поскольку вы уже будете звонить .floatValue!

Также переменные и константы должны начинаться с нижнего регистра (включая IBOutlets)


Расширение не требуется, мост выполняется автоматически Swift, поскольку @tom утверждает, что все, что вам нужно, это Wage.text.floatValue. Не уверен, изменилось ли это между публикацией ответа и сейчас, но это было какое-то время.
— sketchyTech

3
@GoodbyeStackOverflow, я использую Beta 4, и это точно не работает. Может, в Бете 5 поменяли? NSStringимеет floatValueрасширение, но Stringего нет. Получить ошибку:'String' does not have member named floatValue
— Firo

Это могло быть причиной. Кроме того, у вас есть импорт Foundation в верхней части файла?
— sketchyTech

Я не считаю это очень безопасным, по крайней мере, для стандартов Swift, поскольку, если строка не является числом, NSString.floatValue просто возвращает 0. Это должно вызвать исключение или, по крайней мере, вернуть nil.
— Ixx

let floatValue = (Float)(Wage.text)... В Swift 2.0
— TheTiger

23

Потому что в некоторых частях мира, например, вместо десятичной дроби используется запятая. Лучше всего создать NSNumberFormatter для преобразования строки в float.

let numberFormatter = NSNumberFormatter()
numberFormatter.numberStyle = NSNumberFormatterStyle.DecimalStyle
let number = numberFormatter.numberFromString(self.stringByTrimmingCharactersInSet(Wage.text))

18

Я конвертирую String в Float следующим образом:

let numberFormatter = NSNumberFormatter()
let number = numberFormatter.numberFromString("15.5")
let numberFloatValue = number.floatValue

println("number is \(numberFloatValue)") // prints "number is 15.5"

Я думаю, что это лучшее решение (по крайней мере, для Swift 4+), основная причина в том, что он возвращает необязательный (в отличие от NSString.floatValue, который просто возвращается, 0если что-то не так). Обратите внимание, что это NSNumberFormatterбыло изменено NumberFormatter.
— Rom

9

Обновить

Принятый ответ показывает более современный способ сделать

Swift 1

Вот как Пол Хегарти показал себя на занятии CS193p в Стэнфорде в 2015 году:

wageConversion = NSNumberFormatter().numberFromString(wage.text!)!.floatValue

Вы даже можете создать вычисляемое свойство, чтобы не делать этого каждый раз

var wageValue: Float {
        get {
            return NSNumberFormatter().numberFromString(wage.text!)!.floatValue
        }
        set {
            wage.text = "\(newValue)"
        }
    }

5

Используя принятое решение, я обнаружил, что мой "1.1" (при использовании преобразования .floatValue) будет преобразован в 1.10000002384186, чего я не хотел. Однако, если бы я использовал вместо этого .doubleValue, я бы получил желаемый 1.1.

Так, например, вместо принятого решения я использовал следующее:

var WageConversion = (Wage.text as NSString).doubleValue

В моем случае мне не требовалась двойная точность, но использование .floatValue не давало мне правильного результата.

Просто хотел добавить это к обсуждению на случай, если кто-то еще столкнулся с той же проблемой.


5

Ниже вы найдете дополнительный поплавок, вставьте! в конце, если вы знаете, что это Float, или используйте if / let.

let wageConversion = Float(wage.text)

4

Вот адаптация Swift 3 решения Пола Хегарти из ответа rdprado с некоторой проверкой добавленных к нему опций (возвращение 0,0, если какая-либо часть процесса не работает):

var wageFloat:Float = 0.0

if let wageText = wage.text {
    if let wageNumber = NumberFormatter().number(from: wageText) {
        wageFloat = wageNumber.floatValue
    }
}

Между прочим, я посещал Стэнфордский класс CS193p в iTunes University, когда он еще преподавал Objective-C.

Я обнаружил, что Пол Хегарти - ФАНТАСТИЧЕСКИЙ инструктор, и я очень рекомендую этот класс всем, кто только начинает заниматься iOS-разработкой на Swift !!!


1
Это единственный правильный ответ для Swift 3 или новее. Вы должны использовать a NumberFormatterдля работы с числами с плавающей запятой, введенными пользователем.
— rmaddy

3
import Foundation
"-23.67".floatValue // => -23.67

let s = "-23.67" as NSString
s.floatValue // => -23.67

3
Объясните, почему этот код работает. Это предотвращает копирование и вставку без понимания его работы.
— rayryeng



1

У вас есть два варианта, очень похожих (по подходу и результату):

// option 1:
var string_1 : String = "100"
var double_1 : Double = (string_1 as NSString).doubleValue + 99.0

// option 2: 
var string_2 : NSString = "100"
// or:  var string_2 = "100" as NSString
var number_2 : Double = string_2.doubleValue;

2
bridgeToObjectiveC () был удален в Beta 5
— carmen_munich

1

Double() строит Double из Int, например:

var convertedDouble = Double(someInt)

Обратите внимание, что это будет работать только в том случае, если ваш текст действительно содержит число. Поскольку Wageэто текстовое поле, пользователь может вводить все, что хочет, и это вызовет ошибку времени выполнения, когда вы перейдете к распаковке Optional, возвращенного из toInt(). Перед принудительной распаковкой необходимо убедиться, что преобразование прошло успешно.

if let wageInt = Wage.text?.toInt() {
    //we made it in the if so the conversion succeeded.
    var wageConversionDouble = Double(wageInt)
}

Редактировать:

Если вы уверены, что текст будет целым числом, вы можете сделать что-то вроде этого (обратите внимание, что textUITextField также является необязательным)):

if let wageText = Wage.text {
    var wageFloat = Double(wageText.toInt()!)
}

Ну, я разрешаю пользователю вводить только числа, поскольку клавиатура представляет собой десятичную клавиатуру, поэтому они не могут вводить ничего, кроме цифр.
— Стивен Фокс

1
wageConversionFloatникогда не будет float, он вылетает напрямую, если входная строка является чем-то вроде float 234.56. как это могло быть принятым / одобренным решением ...?
— holex 06

Этот ответ не работает, если текст содержит десятичное значение. Пример - этот ответ вернется, 3если в текстовом поле есть 3.5. Это происходит потому , что текст первого превращают в Int, затем Intпреобразуется в Float.
— rmaddy 06

1
@StephenFox Имейте в виду, что пользователь может вставлять нечисловой текст в текстовое поле или у пользователя может быть внешняя клавиатура. Никогда не полагайтесь только на клавиатуру для ввода данных.
— rmaddy 06

на самом деле он работает с целыми числами, а не с десятичными. десятичная дробь вызовет фатальную ошибку!
— Miles Works

1

Я нашел другой способ взять входное значение UITextField и преобразовать его в число с плавающей запятой:

    var tempString:String?
    var myFloat:Float?

    @IBAction func ButtonWasClicked(_ sender: Any) {
       tempString = myUITextField.text
       myFloat = Float(tempString!)!
    }

1

ты можешь использовать,

let wg = Float(wage.text!)

Если вы хотите округлить число с плавающей запятой до двух знаков после запятой:

let wg = Float(String(format: "%.2f",wage.text!)

0

Вот как я подошел к этому. Я не хотел «переходить мост», так как он все равно был удален из Xcode 6 beta 5, быстро и грязно:

extension String {

    // converting a string to double
    func toDouble() -> Double? {

        // split the string into components
        var comps = self.componentsSeparatedByString(".")

        // we have nothing
        if comps.count == 0 {
            return nil
        }
        // if there is more than one decimal
        else if comps.count > 2 {
            return nil
        }
        else if comps[0] == "" || comps[1] == "" {
            return nil
        }

        // grab the whole portion
        var whole = 0.0
        // ensure we have a number for the whole
        if let w = comps[0].toInt() {
            whole = Double(w)
        }
        else {
            return nil
        }

        // we only got the whole
        if comps.count == 1 {

            return whole

        }

        // grab the fractional
        var fractional = 0.0
        // ensure we have a number for the fractional
        if let f = comps[1].toInt() {

            // use number of digits to get the power
            var toThePower = Double(countElements(comps[1]))

            // compute the fractional portion
            fractional = Double(f) / pow(10.0, toThePower)

        }
        else {
            return nil
        }

        // return the result
        return whole + fractional
    }

    // converting a string to float
    func toFloat() -> Float? {

        if let val = self.toDouble() {
            return Float(val)
        }
        else {
            return nil
        }

    }

}


// test it out
var str = "78.001"

if let val = str.toFloat() {
    println("Str in float: \(val)")
}
else {
    println("Unable to convert Str to float")
}

// now in double
if let val = str.toDouble() {
    println("Str in double: \(val)")
}
else {
    println("Unable to convert Str to double")
}

1
Потому что в некоторых частях мира, например, вместо десятичной дроби используется запятая. Лучше всего создать NSNumberFormatter для преобразования строки в float. Посмотрите ответ @DmitriFuerle
— carmen_munich

@PartialFrozenOJ Вы пробовали использовать toDouble()функцию со строкой «10», я имею в виду, если нет десятичной дроби. Он все равно рухнет. Потому что в этом случае count будет 1, и вы не справитесь с этим. Он рухнет в else if comps[0] == "" || comps[1] == "". Во всяком случае, вы так серьезно относитесь к обращению.
— TheTiger

@PartialFrozenOJ Но если бы в 2014 году состояние было таким же. В любом случае нет проблем!
— TheTiger

0

Для полноты картины это решение, использующее расширение, UITextFieldкоторое также может учитывать другую локаль.

Для Swift 3+

extension UITextField {
    func floatValue(locale : Locale = Locale.current) -> Float {
        let numberFormatter = NumberFormatter()
        numberFormatter.numberStyle = .decimal
        numberFormatter.locale = locale

        let nsNumber = numberFormatter.number(from: text!)
        return nsNumber == nil ? 0.0 : nsNumber!.floatValue
    }
}

В качестве общего решения это, вероятно, должно возвращать a, Float?а не обрабатывать недопустимые значения как 0.0. Позвольте вызывающей стороне сделать что-то вроде того, let val = field.floatValue ?? 0.0если в данном случае плохой результат должен быть равен нулю.
— rmaddy

0

Swift 4/5, используйте только Float (value).

let string_value : String = "123200"

let float_value : Float = Float(string_value)

print(float_value)

Ответ: 123200


-1

Использовать это:

 // get the values from text boxes
    let a:Double = firstText.text.bridgeToObjectiveC().doubleValue
    let b:Double = secondText.text.bridgeToObjectiveC().doubleValue

//  we checking against 0.0, because above function return 0.0 if it gets failed to convert
    if (a != 0.0) && (b != 0.0) {
        var ans = a + b
        answerLabel.text = "Answer is \(ans)"
    } else {
        answerLabel.text = "Input values are not numberic"
    }

1
bridgeToObjectiveC () был удален в Beta 5
— carmen_munich

-4

Простой способ:

// toInt returns optional that's why we used a:Int?
let a:Int? = firstText.text.toInt()
let b:Int? = secondText.text.toInt()

// check a and b before unwrapping using !
if a && b {
    var ans = a! + b!
    answerLabel.text = "Answer is \(ans)"
} else {
    answerLabel.text = "Input values are not numberic"
}

вы можете использовать тот же подход для других расчетов, надеюсь, это поможет !!


3
Как бы хорошо это ни было, он просилfloat
— Джек
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.