Преобразование строки в плавающую в 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.