Преобразование строки в float в Swift от Apple

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

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

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

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

Я знаю, как преобразовать их в целое, делая это:

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

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

16 ответов


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)


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

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

я преобразую строку в Float таким образом:

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

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

обновление

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

Swift 1

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

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

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

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

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

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

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

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

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


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

let wageConversion = Float(wage.text)

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

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

вот быстрая адаптация 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!!!


extension String {    
    func floatValue() -> Float? {
        if let floatval = Float(self) {
            return floatval
        }
        return nil
    }
}

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

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

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

var convertedDouble = Double(someInt)

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

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

Edit:

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

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

вот как я подошел к этому. Я не хотел "пересекать мост", так как он был удален из 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")
}

для полноты это решение, использующее расширение 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
    }
}

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

    var tempString:String?
    var myFloat:Float?

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

используйте этот:

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

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

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

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