Convertir cadena para flotar en Apple’s Swift

Estoy tratando de convertir los números tomados de un UITextField, que supongo que son en realidad cadenas, y convertirlos en flotantes, para poder multiplicarlos.

Tengo dos UITextfield s que se declaran de la siguiente manera:

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

Cuando el usuario presiona un UIButton, 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 a un número entero haciendo esto:

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

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

Swift 2.0+

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

Si quiere un valor 0 para un Float no válido por alguna razón, puede usar Float(Wage.text) ?? 0 Float(Wage.text) ?? 0 que devolverá 0 si no es un Float válido.


Vieja solución

La mejor manera de manejar esto es el casting directo:

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

De hecho, creé una extension para usar mejor esto también:

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

¡Ahora puede simplemente llamar a var WageConversion = Wage.text.floatValue y permitir que la extensión maneje el 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.34 , o incluso 12.12.41 ).

Obviamente, si Apple agrega un floatValue a Swift, 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á perfectamente, ¡ya que usted estará llamando a .floatValue !

Además, las variables y las constantes deben comenzar con una minúscula (incluidos IBOutlets )

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

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

Convierto String to 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" 

Actualizar

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

Swift 1

Así es como Paul Hegarty ha demostrado 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)" } } 

Utilizando la solución aceptada, descubrí que mi “1.1” (al usar la conversión .floatValue) se convertiría a 1.10000002384186, que no era lo que yo quería. Sin embargo, si usara el .doubleValue, 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 precisión doble, pero usar .floatValue no me daba el resultado correcto.

Solo quería agregar esto a la discusión en caso de que alguien más haya tenido el mismo problema.

A continuación, le dará un Flotador opcional, ¡adhiera un! al final si sabes que es un Float, o usa if / let.

 let wageConversion = Float(wage.text) 
 import Foundation "-23.67".floatValue // => -23.67 let s = "-23.67" as NSString s.floatValue // => -23.67 

Aquí hay una adaptación de Swift 3 de la solución de Paul Hegarty a partir de la respuesta de rdprado, con algunas comprobaciones de opciones adicionales (retornando 0.0 si alguna parte del proceso falla):

 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 aún enseñaba Objective-C.

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

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

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

Double() crea un Double desde un Int, como este:

var convertedDouble = Double(someInt)

Tenga en cuenta que esto solo funcionará si su texto contiene realmente un número. Como Wage es un campo de texto, el usuario puede ingresar lo que quiera y esto generará un error de tiempo de ejecución cuando vaya a unbox la Opcional devuelta desde toInt() . Debería verificar que la conversión tuvo éxito 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 en cuenta que el text en UITextField también es opcional)):

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

Así es como me acerqué. 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") } 

En aras de la exhaustividad, esta es una solución que utiliza una extensión de UITextField que 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 } } 

Utilizar esta:

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

Camino 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 esta ayuda!