Convertir cadena en flotante en Swift


101

Estoy tratando de convertir números tomados de un UITextField, que supongo, son en realidad Strings, y convertirlos a Float, para poder multiplicarlos.

Tengo dos UITextfields que se declaran de la siguiente manera:

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

Cuando el usuario presiona un botón UIB, quiero calcular los salarios que gana el usuario, pero no puedo, ya que primero necesito convertirlos en flotadores, antes de poder usarlos.

Sé cómo convertirlos en un número entero haciendo esto:

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

Sin embargo, no tengo idea de cómo convertirlos en flotantes.

Respuestas:


200

Swift 2.0+

Ahora, con Swift 2.0 , puede usar Float(Wage.text)que devuelve un Float?tipo. Más claro que la siguiente solución que acaba de regresar 0.

Si desea un 0valor para un inválido Floatpor alguna razón, puede usar el Float(Wage.text) ?? 0que se devolverá 0si no es válido Float.


Solución antigua

La mejor manera de manejar esto es el casting directo:

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

De hecho, creé un extensionpara usar mejor esto también:

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

¡Ahora puede llamar var WageConversion = Wage.text.floatValuey permitir que la extensión se encargue del puente por usted!

Esta es una buena implementación ya que puede manejar flotantes reales (entrada con .) y también ayudará a evitar que el usuario copie texto en su campo de entrada ( 12p.34o incluso 12.12.41).

Obviamente, si Apple agrega un floatValuea Swift, esto arrojará una excepción, pero puede ser bueno mientras tanto. Si lo agregan más tarde, entonces todo lo que necesita hacer para modificar su código es eliminar la extensión y todo funcionará a la perfección, ¡ya que ya estará llamando .floatValue!

Además, las variables y constantes deben comenzar con minúsculas (incluidas IBOutlets)


La extensión no es necesaria, Swift realiza el puente automáticamente, ya que @tom indica que todo lo que necesita es Wage.text.floatValue. No estoy seguro de si esto cambió entre la publicación de la respuesta y ahora, pero ha estado ahí por un tiempo.
sketchyTech

3
@GoodbyeStackOverflow, estoy usando Beta 4 y definitivamente no funciona. ¿Quizás lo cambiaron en Beta 5? NSStringtiene floatValueextensión pero Stringno la tiene. Obtener error:'String' does not have member named floatValue
Firo

Ésta podría ser la razón. Además, ¿tiene Import Foundation en la parte superior de su archivo?
sketchyTech

No considero que esto sea muy seguro, al menos para los estándares Swift, ya que si la cadena no es un número, NSString.floatValue simplemente devuelve 0. Esto debería activar una Excepción o al menos devolver nil.
Ixx

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

23

Porque en algunas partes del mundo, por ejemplo, se usa una coma en lugar de un decimal. Es mejor crear un NSNumberFormatter para convertir una cadena en flotante.

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

18

Convierto String a Float de esta manera:

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

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

Creo que esta es la mejor solución (al menos para swift 4+), la razón principal es que devuelve un opcional (a diferencia de NSString.floatValue, que simplemente regresa 0si algo está mal). Tenga en cuenta que NSNumberFormatterse cambió NumberFormatter.
Rom

9

Actualizar

La respuesta aceptada muestra una forma más actualizada de hacer

Rápido 1

Así ha demostrado Paul Hegarty en la clase CS193p de Stanford en 2015:

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

Incluso puede crear una propiedad calculada para no tener que hacer eso cada vez

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

5

Usando la solución aceptada, descubrí que mi "1.1" (cuando usaba la conversión .floatValue) se convertiría en 1.10000002384186, que no era lo que quería. Sin embargo, si usara .doubleValue en su lugar, obtendría el 1.1 que quería.

Entonces, por ejemplo, en lugar de usar la solución aceptada, usé esto en su lugar:

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

En mi caso, no necesitaba doble precisión, pero usar .floatValue no me estaba dando el resultado adecuado.

Solo quería agregar esto a la discusión en caso de que alguien más se hubiera encontrado con el mismo problema.


5

A continuación se le dará un flotador opcional, pegue un! al final si sabe que es un Float, o use if / let.

let wageConversion = Float(wage.text)

4

Aquí hay una adaptación de Swift 3 de la solución de Paul Hegarty de la respuesta de rdprado, con algunas comprobaciones de opcionales agregadas (devolviendo 0.0 si falla alguna parte del proceso):

var wageFloat:Float = 0.0

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

Por cierto, tomé la clase CS193p de Stanford usando la Universidad de iTunes cuando todavía estaba enseñando Objective-C.

Encontré a Paul Hegarty como un instructor FANTÁSTICO, y recomendaría la clase a cualquiera que esté comenzando como desarrollador de iOS en Swift.


1
Esta es la única respuesta correcta para Swift 3 o posterior. Debe utilizar un NumberFormatterpara tratar los números de punto flotante introducidos por el usuario.
rmaddy

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

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

3
Explique por qué funciona este código. Esto evita copiar y pegar sin comprender su funcionamiento.
rayryeng

3

En rápido 4

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

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


1

Tiene dos opciones que son bastante similares (por el enfoque y el 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 () fue eliminado en Beta 5
carmen_munich

1

Double() construye un Double a partir de un Int, así:

var convertedDouble = Double(someInt)

Tenga en cuenta que esto solo funcionará si su texto realmente contiene un número. Como Wagees un campo de texto, el usuario puede ingresar lo que quiera y esto desencadenará un error de tiempo de ejecución cuando vaya a desempaquetar el Opcional devuelto toInt(). Debe verificar que la conversión se haya realizado correctamente antes de forzar el desempaquetado.

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

Editar:

Si está seguro de que el texto será un número entero, puede hacer algo como esto (tenga texten cuenta que en UITextField también es opcional)):

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

Bueno, solo estoy permitiendo que el usuario ingrese números ya que el teclado es un teclado decimal, por lo que en realidad no pueden ingresar nada más que números.
Stephen Fox

1
wageConversionFloatnunca será el flotador, se bloquea directamente si la cadena de entrada es una especie de flotador 234.56. ¿cómo podría ser una solución aceptada / votada a favor ...?
holex

Esta respuesta no funciona si el texto contiene un valor decimal. Ejemplo: esta respuesta volverá 3si el campo de texto tiene 3.5. Esto se debe a que el texto se convierte primero en un Int, luego Intse convierte en un Float.
rmaddy

1
@StephenFox Tenga en cuenta que un usuario puede pegar texto no numérico en el campo de texto o el usuario puede tener un teclado externo. Nunca confíe solo en el teclado para garantizar la entrada de datos.
rmaddy

en realidad funciona, con números enteros, pero no con decimales. ¡un decimal arrojará un error fatal!
Miles Works

1

Encontré otra forma de tomar un valor de entrada de un UITextField y convertirlo en un flotador:

    var tempString:String?
    var myFloat:Float?

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

1

puedes usar,

let wg = Float(wage.text!)

Si desea redondear el flotador a 2 decimales:

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

0

Así es como lo abordé. No quería "cruzar el puente", ya que se ha eliminado de Xcode 6 beta 5 de todos modos, rápido y sucio:

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 en algunas partes del mundo, por ejemplo, se usa una coma en lugar de un decimal. Es mejor crear un NSNumberFormatter para convertir una cadena en flotante. Mira la respuesta de @DmitriFuerle
carmen_munich

@PartiallyFrozenOJ ¿Has probado la toDouble()función con la cadena "10", quiero decir, si no hay decimal. De todos modos se estrellará. Porque en ese caso el recuento será 1 y no lo estás manejando. Se estrellará en else if comps[0] == "" || comps[1] == "". De todos modos, eres tan serio en la conversión.
TheTiger

@PartiallyFrozenOJ Pero si la condición fue la misma en 2014 también. De todos modos ¡No hay problema!
TheTiger

0

En aras de la integridad, esta es una solución que utiliza una extensión de la UITextFieldcual también puede considerar una configuración regional 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 solución general, esto probablemente debería devolver un Float?y no tratar los valores no válidos como 0.0. Deje que la persona que llama haga algo como let val = field.floatValue ?? 0.0si un caso dado debería tratar el mal resultado como cero.
rmaddy

0

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

let string_value : String = "123200"

let float_value : Float = Float(string_value)

print(float_value)

Respuesta: 123200


-1

Utilizar este:

 // 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 () fue eliminado en Beta 5
carmen_munich

-4

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

puede usar el mismo enfoque para otros cálculos, ¡espero que esto ayude!


3
Por muy bueno que sea, estaba pidiendofloat
Jack
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.