Перетворити рядок в плаваючий в Swift


101

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

У мене є два UITextfields, які оголошені так:

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

Коли користувач натискає UIButton, я хочу обчислити заробітну плату, яку отримує користувач, але я не можу, оскільки мені потрібно перетворити їх у плаваючі елементи, перш ніж я можу їх використовувати.

Я знаю, як перетворити їх у ціле число, зробивши це:

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

Однак я не маю уявлення, як перетворити їх на плавки.

Відповіді:


200

Швидкий 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 все ж додасть floatValueSwift, це викине виняток, але це може бути приємно в той час. Якщо вони все-таки додадуть його пізніше, тоді все, що вам потрібно зробити, щоб змінити код - це видалити розширення, і все буде працювати безперешкодно, оскільки ви вже будете телефонувати .floatValue!

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


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

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

Це може бути причиною. Також у вас є імпортний фонд у верхній частині файлу?
sketchyTech

Я не вважаю це дуже безпечним, принаймні для стандартів Swift, оскільки якщо рядок не є числом, NSString.floatValue просто повертає 0. Це повинно викликати виняток або принаймні повернути нуль.
Ixx

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

23

Тому що в деяких частинах світу, наприклад, кома використовується замість десяткової. Найкраще створити NSNumberFormatter для перетворення рядка в плаваючий.

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"

Я думаю, що це найкраще рішення (принаймні для швидких 4+), головна причина - повернення факультативного (на відміну від NSString.floatValue, яке просто повертається, 0якщо щось не так). Зауважте, що NSNumberFormatterбуло змінено NumberFormatter.
Рим

9

Оновлення

Прийнята відповідь показує більш сучасний спосіб виконання

Швидкий 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, stick a! наприкінці, якщо ви знаєте, що це Float, або використовувати if / let.

let wageConversion = Float(wage.text)

4

Ось адаптація рішення Пола Гегарті з відповіді rdprado на Swift 3 з додаванням перевірки на наявність додаткових опцій (повернення 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.

Я знайшов Пола Гегарті інструктором FANTASTIC, і настійно рекомендую клас усім, хто починає розробник iOS в Swift !!!


1
Це єдина правильна відповідь для Swift 3 або пізнішої версії. Потрібно скористатися NumberFormatterоперацією з введеними користувачем номерами плаваючої крапки.
rmaddy

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

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

3
Поясніть, чому цей код працює. Це запобігає копіюванню та вставленню без розуміння його роботи.
rayryeng

3

У швидкому 4

let Totalname = "10.0" //Now it is in string

let floatVal  = (Totalname as NSString).floatValue //Now converted to float


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 () було видалено в бета-версії 5
carmen_munich

1

Double() створює 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)
}

Редагувати:

Якщо ви впевнені, що текст буде цілим числом, ви можете зробити щось подібне (зауважте, що textна UITextField також необов'язково)):

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

Ну, я дозволяю користувачеві лише вводити цифри, оскільки клавіатура - це десяткова площадка, тому вони фактично не можуть вводити нічого, крім цифр.
Стівен Фокс

1
wageConversionFloatніколи не буде поплавцем, він руйнується безпосередньо, якщо вхідний рядок є подібним поплавком 234.56. як це може бути прийняте / схвалене рішення ...?
holex

Ця відповідь не працює, якщо текст містить десяткове значення. Приклад - ця відповідь повернеться, 3якщо є текстове поле 3.5. Це пояснюється тим, що текст спочатку перетворюється на Int, потім Intперетворюється на a Float.
rmaddy

1
@StephenFox Майте на увазі, що користувач може вставити нечисловий текст у текстове поле або у користувача може бути зовнішня клавіатура. Ніколи не покладайтеся лише на клавіатуру, щоб забезпечити введення даних.
rmaddy

насправді це працює, цілими числами, просто не десяткові. десяткова сторона призведе до фатальної помилки!
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 для перетворення рядка в плаваючий. Подивіться на відповідь @DmitriFuerle
carmen_munich

@ParicallyFrozenOJ Ви пробували toDouble()функцію зі строкою "10", я маю на увазі, якщо немає десяткової. Вона все одно розбиється. Тому що в такому випадку кількість буде 1, і ви з цим не впораєтеся. Він обвалиться на else if comps[0] == "" || comps[1] == "". У будь-якому випадку ви настільки серйозні в конверсії.
TheTiger

@ParicallyFrozenOJ Але якщо б умова була такою ж і в 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

Швидкий 4/5, використовуйте просто Float (значення).

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 () було видалено в бета-версії 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.