แปลง String เป็น Float ใน Swift


101

ฉันกำลังพยายามแปลงตัวเลขที่นำมาจาก UITextField ซึ่งฉันคิดว่าเป็นสตริงจริงและแปลงเป็น Float ดังนั้นฉันจึงสามารถคูณได้

ฉันมีสองตัวUITextfieldที่ประกาศดังนี้:

@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ซึ่งจะกลับมาถ้ามันไม่ถูกต้อง0Float


โซลูชันเก่า

วิธีที่ดีที่สุดในการจัดการสิ่งนี้คือการหล่อโดยตรง:

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 เพิ่ม a floatValueให้กับ Swift สิ่งนี้จะทำให้เกิดข้อยกเว้น แต่มันอาจจะดีในเวลานั้น หากพวกเขาเพิ่มในภายหลังสิ่งที่คุณต้องทำในการแก้ไขโค้ดของคุณคือลบส่วนขยายและทุกอย่างจะทำงานได้อย่างราบรื่นเนื่องจากคุณจะโทรไปแล้ว.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

นี่อาจเป็นเหตุผล นอกจากนี้คุณมีการนำเข้า Foundation ที่ด้านบนของไฟล์หรือไม่?
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"

ฉันคิดว่านี่เป็นทางออกที่ดีที่สุด (อย่างน้อยก็สำหรับ Swift 4+) เหตุผลหลักคือส่งคืนตัวเลือก (ซึ่งตรงข้ามกับNSString.floatValueซึ่งจะส่งคืน0หากมีบางอย่างผิดปกติ) ทราบว่าได้มีการเปลี่ยนแปลงNSNumberFormatter NumberFormatter
รม

9

อัปเดต

คำตอบที่ได้รับการยอมรับจะแสดงวิธีการดำเนินการที่ทันสมัยมากขึ้น

สวิฟต์ 1

นี่คือวิธีที่ Paul Hegarty แสดงในคลาส CS193p ของ Stanford ในปี 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

ในกรณีของฉันฉันไม่ต้องการความแม่นยำสองเท่า แต่การใช้. flloatValue ไม่ได้ให้ผลลัพธ์ที่เหมาะสมกับฉัน

แค่อยากจะเพิ่มสิ่งนี้ในการสนทนาในกรณีที่มีคนอื่นประสบปัญหาเดียวกัน


5

ด้านล่างนี้จะมี Float เสริมให้คุณติด! ในตอนท้ายถ้าคุณรู้ว่ามันเป็น Float หรือใช้ if / let

let wageConversion = Float(wage.text)

4

นี่คือการปรับ Swift 3 ของโซลูชันของ Paul Hegarty จากคำตอบของ rdprado โดยมีการตรวจสอบตัวเลือกที่เพิ่มเข้ามา (คืนค่า 0.0 หากส่วนใดส่วนหนึ่งของกระบวนการล้มเหลว):

var wageFloat:Float = 0.0

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

ยังไงก็ตามฉันเรียน CS193p ของ Stanford โดยใช้ iTunes University ตอนที่ยังสอน Objective-C อยู่

ฉันพบว่า Paul Hegarty เป็นผู้สอนที่ยอดเยี่ยมและฉันขอแนะนำชั้นเรียนนี้ให้กับทุกคนที่เริ่มต้นเป็นนักพัฒนา 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



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เป็นเขตข้อความที่ผู้ใช้สามารถป้อนสิ่งที่พวกเขาต้องการและนี้จะก่อให้เกิดข้อผิดพลาด runtime เมื่อคุณไป unbox 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()!)
}

ฉันอนุญาตให้ผู้ใช้ป้อนตัวเลขเท่านั้นเนื่องจากปุ่มกดเป็น Decimal Pad ดังนั้นจึงไม่สามารถป้อนอะไรได้นอกจากตัวเลข
Stephen Fox

1
wageConversionFloat234.56จะไม่ลอยก็เกิดปัญหาโดยตรงหากสายป้อนเป็นชนิดของลอยเหมือน มันจะเป็นโซลูชันที่ยอมรับ / โหวตได้อย่างไร ... ?
holex

คำตอบนี้ใช้ไม่ได้หากข้อความมีค่าทศนิยม เช่น - คำตอบนี้จะกลับมาถ้าฟิลด์ข้อความมี3 3.5เนื่องจากข้อความถูกแปลงเป็นไฟล์Intก่อนจากนั้นIntจึงแปลงเป็น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!)

หากคุณต้องการปัดเศษทศนิยมให้เป็นทศนิยม 2 ตำแหน่ง:

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

@PartiallyFrozenOJ คุณได้ลองใช้toDouble()ฟังก์ชันกับสตริง "10" แล้วหรือยังฉันหมายถึงถ้าไม่มีทศนิยม มันจะพังอยู่ดี เนื่องจากในกรณีนั้นจำนวนจะเป็น 1 และคุณไม่ได้จัดการสิ่งนั้น มันจะผิดพลาดที่else if comps[0] == "" || comps[1] == "". อย่างไรก็ตามคุณจริงจังมากในการเปลี่ยนใจเลื่อมใส
TheTiger

@PartiallyFrozenOJ แต่ถ้าปี 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
    }
}

ในฐานะที่เป็นวิธีการแก้ปัญหาทั่วไปนี้อาจจะกลับมาและไม่รักษาค่าที่ไม่ถูกต้องเป็นFloat? 0.0ให้ผู้โทรทำบางอย่างเช่นlet val = field.floatValue ?? 0.0กรณีที่กำหนดควรถือว่าผลลัพธ์ที่ไม่ดีเป็นศูนย์
rmaddy


-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
แจ็ค
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.