Converter String em Float em Swift


101

Estou tentando converter números retirados de um UITextField, que presumo que sejam na verdade Strings, e convertê-los em Float, para que possa multiplicá-los.

Eu tenho dois UITextfields que são declarados da seguinte forma:

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

Quando o usuário pressiona um UIButton, quero calcular os salários que o usuário ganha, mas não posso, pois preciso primeiro convertê-los em flutuadores, antes de poder usá-los.

Eu sei como convertê-los em um número inteiro fazendo o seguinte:

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

No entanto, não tenho ideia de como convertê-los em flutuadores.

Respostas:


200

Swift 2.0+

Agora, com o Swift 2.0, você pode apenas usar o Float(Wage.text)que retorna um Float?tipo. Mais claro do que a solução abaixo que apenas retorna 0.

Se você quiser um 0valor para um inválido Floatpor algum motivo, pode usar Float(Wage.text) ?? 0que retornará 0se não for válido Float.


Solução Antiga

A melhor maneira de lidar com isso é a conversão direta:

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

Na verdade, criei um extensionpara usar melhor isso também:

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

Agora você pode apenas ligar var WageConversion = Wage.text.floatValuee permitir que o ramal controle a ponte para você!

Esta é uma boa implementação, pois pode lidar com flutuações reais (entrada com .) e também ajudará a evitar que o usuário copie o texto em seu campo de entrada ( 12p.34ou mesmo 12.12.41).

Obviamente, se a Apple adicionar um floatValueao Swift, isso lançará uma exceção, mas pode ser bom nesse meio tempo. Se eles adicionarem mais tarde, tudo o que você precisa fazer para modificar seu código é remover a extensão e tudo funcionará perfeitamente, pois você já estará ligando .floatValue!

Além disso, as variáveis ​​e constantes devem começar com minúsculas (incluindo IBOutlets)


A extensão não é necessária, a ponte é feita automaticamente pelo Swift, como @tom afirma que tudo que você precisa é Wage.text.floatValue. Não tenho certeza se isso mudou entre a resposta postada e agora, mas já está lá há algum tempo.
sketchyTech

3
@GoodbyeStackOverflow, estou usando o Beta 4 e definitivamente não funciona. Talvez eles tenham mudado no Beta 5? NSStringtem floatValueextensão, mas Stringnão tem. Obter erro:'String' does not have member named floatValue
Firo

Esse pode ser o motivo. Além disso, você tem o import Foundation no topo do seu arquivo?
sketchyTech

Não considero isso muito seguro, pelo menos para os padrões do Swift, pois se a string não for um número, NSString.floatValue retorna apenas 0. Isso deve acionar uma Exceção ou pelo menos retornar nulo.
Ixx

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

23

Porque em algumas partes do mundo, por exemplo, uma vírgula é usada em vez de um decimal. É melhor criar um NSNumberFormatter para converter uma string em float.

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

18

Eu converto String em Float desta forma:

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

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

Eu acho que esta é a melhor solução (pelo menos para o swift 4+), o principal motivo é que ele retorna um opcional (ao invés de NSString.floatValue, que simplesmente retorna 0se algo estiver errado.). Observe que NSNumberFormatterfoi alterado NumberFormatter.
Rom

9

Atualizar

A resposta aceita mostra uma forma mais atualizada de fazer

Swift 1

É assim que Paul Hegarty demonstrou na classe CS193p de Stanford em 2015:

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

Você pode até criar uma propriedade computada para não ter que fazer isso todas as vezes

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

5

Usando a solução aceita, eu estava descobrindo que meu "1.1" (ao usar a conversão .floatValue) seria convertido para 1.10000002384186, o que não era o que eu queria. No entanto, se eu usasse o .doubleValue em vez disso, obteria o 1.1 que queria.

Então, por exemplo, em vez de usar a solução aceita, usei esta:

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

No meu caso, não precisei de precisão dupla, mas usar o .floatValue não estava me dando o resultado adequado.

Só queria adicionar isso à discussão, caso outra pessoa esteja enfrentando o mesmo problema.


5

Abaixo, você encontrará um Float opcional, coloque um! no final, se você souber que é um Float, ou use if / let.

let wageConversion = Float(wage.text)

4

Aqui está uma adaptação do Swift 3 da solução de Paul Hegarty da resposta de rdprado, com algumas verificações de opcionais adicionados a ela (retornando 0,0 se qualquer parte do processo falhar):

var wageFloat:Float = 0.0

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

A propósito, eu fiz o curso CS193p de Stanford usando a iTunes University quando ela ainda ensinava Objective-C.

Descobri que Paul Hegarty é um instrutor FANTÁSTICO, e eu recomendo a classe para qualquer pessoa que esteja começando como desenvolvedor iOS em Swift !!!


1
Esta é a única resposta correta para Swift 3 ou posterior. Você deve usar um NumberFormatterpara lidar com os números de ponto flutuante inseridos pelo usuário.
rmaddy de

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

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

3
Explique por que esse código funciona. Isso evita copiar e colar sem compreender seu funcionamento.
rayryeng

3

In swift 4

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

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


1

Você tem duas opções que são bastante semelhantes (pela abordagem e resultado):

// 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 () foi removido do Beta 5
carmen_munich

1

Double() constrói um Double a partir de um Int, assim:

var convertedDouble = Double(someInt)

Observe que isso só funcionará se o seu texto realmente contiver um número. Como Wageé um campo de texto, o usuário pode inserir o que quiser e isso irá disparar um erro de tempo de execução quando você for desempacotar o opcional retornado toInt(). Você deve verificar se a conversão foi bem-sucedida antes de forçar o unboxing.

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

Editar:

Se você tiver certeza de que o texto será um número inteiro, você pode fazer algo assim (observe que textem UITextField também é opcional)):

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

Bem, estou apenas permitindo que o usuário insira números, já que o teclado é um bloco decimal, então eles não podem inserir nada além de números.
Stephen Fox

1
wageConversionFloatnunca será o float, ele trava diretamente se a string de entrada for um tipo de float 234.56. como poderia ser uma solução aceita / votada ...?
holex

Essa resposta não funciona se o texto contiver um valor decimal. Exemplo - esta resposta retornará 3se o campo de texto tiver 3.5. Isso ocorre porque o texto é primeiro convertido em um e Int, em seguida, o Inté convertido em a Float.
rmaddy

1
@StephenFox Lembre-se de que um usuário pode colar texto não numérico no campo de texto ou pode ter um teclado externo. Nunca confie apenas no teclado para garantir a entrada de dados.
rmaddy

na verdade, funciona com números inteiros, mas não decimais. um decimal irá gerar um erro fatal!
Miles Works

1

Eu descobri outra maneira de pegar um valor de entrada de um UITextField e convertê-lo em um float:

    var tempString:String?
    var myFloat:Float?

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

1

você pode usar,

let wg = Float(wage.text!)

Se você quiser arredondar o flutuante para 2 casas decimais:

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

0

É assim que eu abordei. Eu não queria "cruzar a ponte", já que foi removido do Xcode 6 beta 5 de qualquer maneira, rápido e sujo:

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
Porque em algumas partes do mundo, por exemplo, uma vírgula é usada em vez de um decimal. É melhor criar um NSNumberFormatter para converter uma string em float. Veja a resposta de @DmitriFuerle
carmen_munich

@PartiallyFrozenOJ Você tentou toDouble()funcionar com a string "10", quero dizer, se não houver decimal. Vai travar de qualquer maneira. Porque nesse caso a contagem será 1 e você não está lidando com isso. Ele vai travar em else if comps[0] == "" || comps[1] == "". De qualquer forma, você é tão sério na conversão.
TheTiger

@PartiallyFrozenOJ Mas se a condição foi a mesma em 2014 também. Enfim, não tem problema!
TheTiger

0

Para fins de integridade, esta é uma solução que usa uma extensão da UITextFieldqual também pode considerar um local diferente.

Para 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
    }
}

Como uma solução geral, isso provavelmente deve retornar a Float?e não tratar valores inválidos como 0.0. Deixe o chamador fazer algo como let val = field.floatValue ?? 0.0se um determinado caso devesse tratar o resultado ruim como zero.
rmaddy de

0

Swift 4/5, use apenas Float (valor).

let string_value : String = "123200"

let float_value : Float = Float(string_value)

print(float_value)

Resposta: 123200


-1

Usa isto:

 // 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 () foi removido do Beta 5
carmen_munich

-4

Jeito fácil:

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

você pode usar a mesma abordagem para outros cálculos, espero que ajude !!


3
Por melhor que isso seja, ele estava pedindofloat
Jack
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.