Swift - วิธีแปลงสตริงเป็น Double


242

ฉันกำลังพยายามเขียนโปรแกรม BMI ในภาษาที่รวดเร็ว และฉันได้รับปัญหานี้: จะแปลงสตริงเป็นคู่ได้อย่างไร

ใน Objective-C ฉันสามารถทำสิ่งนี้ได้:

double myDouble = [myString doubleValue];

แต่ฉันจะทำสิ่งนี้ในภาษาสวิฟต์ได้อย่างไร


1
สิ่งนี้มีการเปลี่ยนแปลงใน Swift 2 ดูคำตอบใหม่โดยใช้ตัวเริ่มต้นพร้อมใช้งาน Double () ใหม่: stackoverflow.com/a/32850058/276626
Paul Solt

คำตอบ:


205

Swift 4.2+ String เป็น Double

คุณควรใช้ initializers ชนิดใหม่เพื่อแปลงระหว่างชนิดสตริงและตัวเลข (Double, Float, Int) มันจะกลับมาเป็นตัวเลือกประเภท (สองครั้ง?) ซึ่งจะมีค่าที่ถูกต้องหรือไม่มีถ้าสตริงไม่ได้เป็นตัวเลข

หมายเหตุ:ไม่แนะนำให้ใช้คุณสมบัติ NSString doubleValue เนื่องจากจะส่งคืนค่า 0 หากค่าไม่สามารถแปลงได้ (เช่น: อินพุตผู้ใช้ไม่ดี)

let lessPrecisePI = Float("3.14")

let morePrecisePI = Double("3.1415926536")
let invalidNumber = Float("alphabet") // nil, not a valid number

แกะค่าที่จะใช้โดยใช้ if / let

if let cost = Double(textField.text!) {
    print("The user entered a value price of \(cost)")
} else {
    print("Not a valid number: \(textField.text!)")
}

คุณสามารถแปลงตัวเลขและสกุลเงินที่จัดรูปแบบโดยใช้NumberFormatterคลาส

let formatter = NumberFormatter()
formatter.locale = Locale.current // USA: Locale(identifier: "en_US")
formatter.numberStyle = .decimal
let number = formatter.number(from: "9,999.99")

รูปแบบสกุลเงิน

let usLocale = Locale(identifier: "en_US")
let frenchLocale = Locale(identifier: "fr_FR")
let germanLocale = Locale(identifier: "de_DE")
let englishUKLocale = Locale(identifier: "en_GB") // United Kingdom
formatter.numberStyle = .currency

formatter.locale = usLocale
let usCurrency = formatter.number(from: "$9,999.99")

formatter.locale = frenchLocale
let frenchCurrency = formatter.number(from: "9999,99€")
// Note: "9 999,99€" fails with grouping separator
// Note: "9999,99 €" fails with a space before the €

formatter.locale = germanLocale
let germanCurrency = formatter.number(from: "9999,99€")
// Note: "9.999,99€" fails with grouping separator

formatter.locale = englishUKLocale
let englishUKCurrency = formatter.number(from: "£9,999.99")

อ่านเพิ่มเติมเกี่ยวกับฉันโพสต์บล็อกเกี่ยวกับการแปลง String ประเภทคู่ (และเงิน)


2
ปัญหาอื่นคือมันไม่รองรับตัวเลขในภาษาอื่นนอกเหนือจาก 1,000.00 ถ้าคุณใช้รูปแบบอื่นเช่น 1 000,00 มันจะตัดทศนิยม 2 ตำแหน่งในตอนท้าย อย่างน้อยนี่คือสิ่งที่เกิดขึ้นกับ Objective-C - ตามเอกสารประกอบของ Apple: (ไม่ได้ตระหนักถึงสถานที่) วิธีการอำนวยความสะดวกต่อไปนี้จะข้ามอักขระช่องว่างเริ่มต้น (whitespaceSet) และละเว้นอักขระต่อท้าย พวกเขาไม่ได้ตระหนักถึงสถานที่ NSScanner หรือ NSNumberFormatter สามารถใช้สำหรับการแยกตัวเลขที่มีประสิทธิภาพและตระหนักถึงสถานที่
mskw

@mskw ฉันได้เพิ่มรายละเอียดเพิ่มเติมเกี่ยวกับการใช้ NumberFormatter เพื่อแยกวิเคราะห์สกุลเงิน ในรหัสของฉันฉันจะรวมตัวกันหลายตัวจัดรูปแบบพยายามแปลงโดยใช้ไวยากรณ์ if / let เพื่อให้ฉันสามารถแยกทั้งตัวเลขที่จัดรูปแบบสกุลเงิน ($ 1,000.00) หรือตัวเลขที่จัดรูปแบบ (1,000) คุณไม่ทราบว่าผู้ใช้ป้อนหมายเลขได้อย่างไรดังนั้นการสนับสนุนทั้งสองจึงเหมาะกับกลุ่มของคำสั่ง if / let
Paul Solt

276

สวิฟท์ 2 ปรับปรุง มี initializers failable ใหม่ที่ช่วยให้คุณสามารถทำเช่นนี้ในทางสำนวนและมีความปลอดภัยมากขึ้น (เป็นคำตอบที่หลายคนได้ตั้งข้อสังเกตค่า double NSString ไม่ได้ปลอดภัยมากเพราะมันกลับ 0 สำหรับค่าตัวเลขที่ไม่ใช่ว่ามี. ซึ่งหมายความว่าdoubleValueของ"foo"และ"0"มี เหมือน.)

let myDouble = Double(myString)

นี้จะส่งกลับตัวดังนั้นในกรณีเช่นผ่านใน"foo"ที่doubleValueจะได้กลับ 0 intializer failable nilจะกลับมา คุณสามารถใช้guard, if-letหรือmapในการจัดการOptional<Double>

โพสต์ต้นฉบับ: คุณไม่จำเป็นต้องใช้ตัวสร้าง NSString เหมือนคำตอบที่ยอมรับ คุณสามารถบริดจ์มันได้อย่างนี้:

(swiftString as NSString).doubleValue

5
ohai, Jarsen ข้อเสียอย่างหนึ่งของวิธีนี้คือมันจะไม่ล้มเหลวหากสตริงไม่ใช่ double ที่ถูกต้อง แต่คุณจะได้ 0.0 นั่นคือผลจากการ- [NSString doubleValue]เป็นDoubleในรวดเร็ว apposed เป็นไปDouble?( Optional<Double>) สิ่งนี้แตกต่างจากฟังก์ชั่น Swift String toInt()ที่ส่งคืนInt?และระบุในเอกสารว่า "... ยอมรับสตริงที่ตรงกับนิพจน์ทั่วไป" [- +]? [0-9] + "เท่านั้น
Derrick Hathaway

ใช่ใช้.toInt()จะดีกว่า อย่างไรก็ตามนี่เป็นคำตอบเพิ่มเติมเกี่ยวกับวิธีการทำสิ่งเดียวกัน แต่ใน Swift
Jarsen

วิธีนี้จะทำให้คุณเข้าใกล้มูลนิธิอย่างแน่นหนาและมีแนวโน้มว่าจะไม่สามารถใช้งาน Swift ที่ไม่ใช่ของ Apple ได้
Erik Kerber

5
ใน Swift 2.0 Double.init?(_ text: String)ตอนนี้มี initializer พร้อมใช้งาน
mixel

3
นี่ไม่ใช่วิธีที่ดีที่สุด มันจะล้มเหลวขึ้นอยู่กับตัวแยกทศนิยม มันจะดีกับ '.' แต่ไม่ใช่ด้วย ',' NSNumberFormatter จะรองรับตัวคั่นทศนิยมที่ใช้ในการโลคัลไลเซชันปัจจุบัน
Julian Król

75

สำหรับความรู้สึกที่รวดเร็วกว่าเล็กน้อยให้NSFormatter()หลีกเลี่ยงการส่งNSStringและnilเมื่อสตริงไม่มีDoubleค่า (เช่น "test" จะไม่ส่งคืน0.0)

let double = NSNumberFormatter().numberFromString(myString)?.doubleValue

อีกทางเลือกหนึ่งการขยายStringประเภทของ Swift :

extension String {
    func toDouble() -> Double? {
        return NumberFormatter().number(from: self)?.doubleValue
    }
}

และใช้มันเช่นtoInt():

var myString = "4.2"
var myDouble = myString.toDouble()

ส่งคืนตัวเลือกDouble?ที่จะต้องแกะ

ไม่ว่าจะด้วยการบังคับแกะ

println("The value is \(myDouble!)") // prints: The value is 4.2

หรือด้วยคำสั่ง if let:

if let myDouble = myDouble {
    println("The value is \(myDouble)") // prints: The value is 4.2
}

อัปเดต: สำหรับการโลคัลไลเซชันมันเป็นเรื่องง่ายมากที่จะใช้โลแคลกับ NSFormatter ดังนี้:

let formatter = NSNumberFormatter()
formatter.locale = NSLocale(localeIdentifier: "fr_FR")
let double = formatter.numberFromString("100,25")

ในที่สุดคุณสามารถใช้NSNumberFormatterCurrencyStyleในการจัดรูปแบบถ้าคุณทำงานกับสกุลเงินที่สตริงมีสัญลักษณ์สกุลเงิน


ฉันชอบแนวคิดของการขยายคลาส String สำหรับแอปที่จะใช้การแปลงหลายแห่ง แต่ฉันไม่เห็นประโยชน์ของความซับซ้อนของการเรียกใช้ NSNumberFormatter เนื่องจากการส่งไปยัง NSString และการใช้. doubleValue ดูเหมือนว่าอย่างน้อยก็โดยตรงและง่ายต่อการอ่านและจดจำ
clearlight

12
ความจริงแล้วข้อดีของการใช้ NSNumberFormatter () คือเมธอด numberFromString: จะคืนค่าศูนย์ถ้าสตริงมีอักขระที่ไม่ได้เป็นสองเท่า ปัญหาของ doubleValue บน NSString ก็คือมันจะคืนค่า double (0.0 สำหรับ "test" เป็นตัวอย่าง) เสมอโดยไม่คำนึงถึง ดังนั้นหากคุณกำลังจัดการกับสตริงทุกชนิดและคุณต้องการทดสอบว่าสตริงนั้นเป็นเพียงสองเท่าไม่มีอักขระเพิ่มเติมโดยใช้ NSNumberFormatter เป็นวิธีที่จะไป
dirkgroten

4
สิ่งนี้ล้มเหลวในภาษาฝรั่งเศส
ปีเตอร์เค

1
นี่เป็นทางออกที่ยอดเยี่ยม แต่การใช้รหัสนี้เท่านั้นมันจะไม่ทำงานในประเทศที่ใช้เครื่องหมายจุลภาคเป็นตัวคั่น (รวมถึงฝรั่งเศสในชื่อ @PeterK.) ฉันพยายามเขียนความคิดเห็นด้วยวิธีแก้ปัญหา แต่มันนานเกินไปฉันจึงต้องตอบคำถามแทน ไปเลย: วิธีแก้ไข
Jacob R

53

ตัวเลือกอื่นที่นี่กำลังแปลงเป็นNSStringและใช้ที่:

let string = NSString(string: mySwiftString)
string.doubleValue

13
ฉันหวังว่าจะมีวิธีที่ดีกว่าในการทำเช่นนี้ ฉันจะรู้ได้อย่างไรว่าการแยกวิเคราะห์ล้มเหลวตัวอย่างเช่น
Ryan Hoffman

2
@RyanHoffman น่าเสียดายที่สัญญา NSString doubleValue ไม่เคยให้สิ่งใดเลย สิ่งที่คุณจะได้รับคือ 0.0 ถ้าสตริงไม่ได้ขึ้นต้นด้วยการแสดงตัวเลขที่ถูกต้อง, HUGE_VAL และ -HUGE_VAL สำหรับ overflow / underflow หากคุณต้องการทราบว่าทำไมการวิเคราะห์คำล้มเหลวฉันเชื่อว่าคุณต้องมองหา NSNumberFormatter ซึ่งออกแบบมาเพื่อจัดการการแปลงหมายเลข / สตริงในลักษณะที่มีประสิทธิภาพยิ่งขึ้น
Jarsen

เนื่องจากอาจเป็นคำตอบที่หายากนี่คือ:(swiftString as NSString).doubleValue
LearnCocos2D

24

ต่อไปนี้เป็นวิธีการส่วนขยายที่ช่วยให้คุณสามารถเรียก doubleValue () บนสตริง Swift และรับ double backback (ตัวอย่างเอาต์พุตมาก่อน)

println("543.29".doubleValue())
println("543".doubleValue())
println(".29".doubleValue())
println("0.29".doubleValue())

println("-543.29".doubleValue())
println("-543".doubleValue())
println("-.29".doubleValue())
println("-0.29".doubleValue())

//prints
543.29
543.0
0.29
0.29
-543.29
-543.0
-0.29
-0.29

นี่คือวิธีการขยาย:

extension String {
    func doubleValue() -> Double
    {
        let minusAscii: UInt8 = 45
        let dotAscii: UInt8 = 46
        let zeroAscii: UInt8 = 48

        var res = 0.0
        let ascii = self.utf8

        var whole = [Double]()
        var current = ascii.startIndex

        let negative = current != ascii.endIndex && ascii[current] == minusAscii
        if (negative)
        {
            current = current.successor()
        }

        while current != ascii.endIndex && ascii[current] != dotAscii
        {
            whole.append(Double(ascii[current] - zeroAscii))
            current = current.successor()
        }

        //whole number
        var factor: Double = 1
        for var i = countElements(whole) - 1; i >= 0; i--
        {
            res += Double(whole[i]) * factor
            factor *= 10
        }

        //mantissa
        if current != ascii.endIndex
        {
            factor = 0.1
            current = current.successor()
            while current != ascii.endIndex
            {
                res += Double(ascii[current] - zeroAscii) * factor
                factor *= 0.1
                current = current.successor()
           }
        }

        if (negative)
        {
            res *= -1;
        }

        return res
    }
}

ไม่มีการตรวจสอบข้อผิดพลาด แต่คุณสามารถเพิ่มได้หากคุณต้องการ


20

ในฐานะของสวิฟท์ 1.1, คุณโดยตรงสามารถส่งผ่านStringไปยังconst char *พารามิเตอร์

import Foundation

let str = "123.4567"
let num = atof(str) // -> 123.4567

atof("123.4567fubar") // -> 123.4567

หากคุณไม่ชอบเลิกใช้atof:

strtod("765.4321", nil) // -> 765.4321

คำเตือน: NSString.doubleValueการทำงานของการแปลงจะแตกต่างจาก

atofและstrtodยอมรับ0xสตริงเลขฐานสิบหกที่นำหน้า:

atof("0xffp-2") // -> 63.75
atof("12.3456e+2") // -> 1,234.56
atof("nan") // -> (not a number)
atof("inf") // -> (+infinity)

หากคุณต้องการ.doubleValueพฤติกรรมเรายังคงสามารถใช้การCFStringเชื่อมต่อได้:

let str = "0xff"
atof(str)                      // -> 255.0
strtod(str, nil)               // -> 255.0
CFStringGetDoubleValue(str)    // -> 0.0
(str as NSString).doubleValue  // -> 0.0

NSStringฉันเป็นแฟนของวิธีนี้แทนการหล่อไป
Sam Soffes

10

ใน Swift 2.0 วิธีที่ดีที่สุดคือหลีกเลี่ยงการคิดเหมือนนักพัฒนา Objective-C ดังนั้นคุณไม่ควร "แปลงสตริงเป็น Double" แต่คุณควร "เริ่มต้น Double จากสตริง" เอกสารของ Apple ที่นี่: https://developer.apple.com/library/ios//documentation/Swift/Reference/Swift_Double_Structure/index.html#//apple_ref/swift/structctr/Double/s:FSdcFMSdFSSFSqFSDFS

เป็นตัวเลือก init เพื่อให้คุณสามารถใช้ตัวดำเนินการรวมศูนย์ (??) เพื่อตั้งค่าเริ่มต้น ตัวอย่าง:

let myDouble = Double("1.1") ?? 0.0

Double.init?(_ text: String)มีให้ใน Swift 2.0 คุณควรพูดถึงสิ่งนี้ คำตอบอื่น ๆ ที่นี่ไม่ใช่เพราะคนคิดว่าเป็นนักพัฒนา Objective-C แต่เป็นเพราะ initializer นี้ไม่สามารถใช้ได้ก่อนหน้านี้
mixel

แน่นอนว่าคุณพูดถูก นี่มีเฉพาะใน Swift 2.0 ฉันจะพูดถึงมัน :) แต่เช่นเดียวกับในภาษาอื่น ๆ ที่คุณเริ่มต้นประเภทด้วยอีกประเภทหนึ่งและไม่ควรคาดหวังว่าจะสามารถแปลงเป็นประเภทอื่นได้ การอภิปรายยาว แต่ในฐานะที่เป็นนักพัฒนา Obj-C ฉันมีการปฏิบัติที่ไม่ดีมากเมื่อการเข้ารหัสกับสวิฟท์และนี่คือหนึ่งในพวกเขา :)
Toom

10

บนSWIFT 3คุณสามารถใช้:

if let myDouble = NumberFormatter().number(from: yourString)?.doubleValue {
   print("My double: \(myDouble)")
}

หมายเหตุ: - หากสตริงมีอักขระใด ๆ นอกเหนือจากตัวเลขหรือกลุ่มที่เหมาะสมกับโลแคลหรือตัวคั่นทศนิยมการแยกวิเคราะห์จะล้มเหลว - อักขระตัวคั่นช่องว่างนำหน้าหรือต่อท้ายในสตริงจะถูกละเว้น ตัวอย่างเช่นสตริง“ 5”,“ 5” และ“ 5” ทั้งหมดผลิตหมายเลข 5

นำมาจากเอกสาร: https://developer.apple.com/reference/foundation/numberformatter/1408845-number


10

ฉันไม่เห็นคำตอบที่ต้องการ ฉันเพิ่งโพสต์ที่นี่ของฉันในกรณีที่สามารถช่วยให้ทุกคน คำตอบนี้สามารถใช้ได้เฉพาะในกรณีที่คุณไม่จำเป็นต้องรูปแบบที่เฉพาะเจาะจง

สวิฟท์ 3

extension String {
    var toDouble: Double {
        return Double(self) ?? 0.0
    }
}

9

ลองสิ่งนี้:

   var myDouble = myString.bridgeToObjectiveC().doubleValue
   println(myDouble)

บันทึก

ลบออกใน Beta 5 แล้วมันใช้งานไม่ได้อีกแล้ว?


1
bridgeToObjectiveC () ถูกลบใน Xcode 6 Beta 5 วิธี Mr Smiley เป็นวิธีที่เร็วที่สุดที่ฉันเคยพบในตอนนี้
faraquet99

7

นี่คือการสร้างตามคำตอบโดย @Ryu

ทางออกของเขายอดเยี่ยมตราบใดที่คุณอยู่ในประเทศที่ใช้จุดเป็นตัวคั่น โดยค่าเริ่มต้นNSNumberFormatterใช้สถานที่อุปกรณ์ ดังนั้นสิ่งนี้จะล้มเหลวในทุกประเทศที่ใช้เครื่องหมายจุลภาคเป็นตัวคั่นเริ่มต้น (รวมถึงฝรั่งเศสเป็น @PeterK. ดังกล่าว) หากตัวเลขใช้จุดเป็นตัวคั่น (ซึ่งเป็นกรณีปกติ) ในการตั้งค่าภาษาของ NSNumberFormatter นี้ให้เป็น US และใช้จุดเป็นตัวคั่นแทนบรรทัด

return NSNumberFormatter().numberFromString(self)?.doubleValue

กับ

let numberFormatter = NSNumberFormatter()
numberFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
return numberFormatter.numberFromString(self)?.doubleValue

ดังนั้นรหัสเต็มกลายเป็น

extension String {
    func toDouble() -> Double? {
        let numberFormatter = NSNumberFormatter()
        numberFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
        return numberFormatter.numberFromString(self)?.doubleValue
    }
}

หากต้องการใช้สิ่งนี้เพียงโทร "Your text goes here".toDouble()

นี่จะส่งคืนทางเลือก Double?

ดังที่ @Ryu พูดถึงคุณสามารถบังคับให้แกะออกได้:

println("The value is \(myDouble!)") // prints: The value is 4.2

หรือใช้if letคำสั่ง:

if let myDouble = myDouble {
    println("The value is \(myDouble)") // prints: The value is 4.2
}

1
นี่คือคำตอบที่ถูกต้อง รุ่น Swift 3 จะเป็น NumberFormatter().number(from: myString)?.doubleValue
ลัสสิงห์

7

SWIFT 4

extension String {
    func toDouble() -> Double? {
        let numberFormatter = NumberFormatter()
        numberFormatter.locale = Locale(identifier: "en_US_POSIX")
        return numberFormatter.number(from: self)?.doubleValue
    }
}


6

Swift: 4 และ 5

อาจมีสองวิธีในการทำสิ่งนี้:

  1. String -> Int -> Double:

    let strNumber = "314"
    if let intFromString = Int(strNumber){
        let dobleFromInt = Double(intFromString)
        print(dobleFromInt)
    }
  2. String -> NSString -> Double

    let strNumber1 = "314"
    let NSstringFromString = NSString(string: strNumber1)
    let doubleFromNSString = NSstringFromString.doubleValue
    print(doubleFromNSString)

ใช้งานต่อไปที่คุณชอบตามที่คุณต้องการของรหัส


วิธีแรกไม่ได้ผลสำหรับฉัน แต่วิธีที่สองใช้ได้ดีทีเดียว
Saurabh

@Saurabh คุณช่วยอธิบายเพิ่มเติมเกี่ยวกับสายของคุณได้ไหม?
Abhirajsinh Thakore

5

กรุณาตรวจสอบมันบนสนามเด็กเล่น!

let sString = "236.86"

var dNumber = NSNumberFormatter().numberFromString(sString)
var nDouble = dNumber!
var eNumber = Double(nDouble) * 3.7

โดยวิธีการใน Xcode ของฉัน

.toDouble () - ไม่มีอยู่

.doubleValue สร้างค่า 0.0 จากสตริงที่ไม่ใช่ตัวเลข ...


4

1

let strswift = "12"
let double = (strswift as NSString).doubleValue

2

var strswift= "10.6"
var double : Double = NSString(string: strswift).doubleValue 

อาจเป็นความช่วยเหลือสำหรับคุณ


4

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

(myString as NSString).doubleValue

การสร้างจากนั้นคุณสามารถสร้างส่วนขยาย Swift String แบบเนี้ยบได้อย่างราบรื่น:

extension String {
    var doubleValue: Double {
        return (self as NSString).doubleValue
    }
}

สิ่งนี้ช่วยให้คุณใช้โดยตรง:

myString.doubleValue

ซึ่งจะทำการหล่อสำหรับคุณ หาก Apple เพิ่ม a doubleValueให้กับสายอักขระดั้งเดิมคุณเพียงแค่ลบส่วนขยายออกและส่วนที่เหลือของรหัสของคุณจะทำการรวบรวมโดยอัตโนมัติ!


วิธีการของ Apple จะเรียกว่า. toDouble ... เหมือนกับ toInt มันเป็นการละเว้นที่แปลก มีแนวโน้มที่จะได้รับการแก้ไขในเวอร์ชั่น Swift ในอนาคต ฉันชอบวิธีการขยายที่ดีที่สุดรักษารหัสให้สะอาด
n13

ค่าส่งคืนควรเป็น Double NOT a Float
Leo Dabus

4

สวิฟท์ 3

เพื่อล้างทุกวันนี้มีวิธีการเริ่มต้น:

public init?(_ text: String)ของDoubleชั้นเรียน

มันสามารถใช้สำหรับทุกชั้น

let c = Double("-1.0") let f = Double("0x1c.6") let i = Double("inf") ฯลฯ


2

ส่วนขยายพร้อมด้วยโลแคลเผื่อเลือก

Swift 2.2

extension String {
    func toDouble(locale: NSLocale? = nil) -> Double? {
        let formatter = NSNumberFormatter()
        if let locale = locale {
            formatter.locale = locale
        }
        return formatter.numberFromString(self)?.doubleValue
    }
}

สวิฟท์ 3.1

extension String {
    func toDouble(_ locale: Locale) -> Double {
        let formatter = NumberFormatter()
        formatter.numberStyle = .decimal
        formatter.locale = locale
        formatter.usesGroupingSeparator = true
        if let result = formatter.number(from: self)?.doubleValue {
            return result
        } else {
            return 0
        }
    }
}

1
ฉันได้เพิ่มตัวอย่าง Swift 3.1 คุณหมายถึง "... และเพิ่มตัวอย่างสำหรับภาษา" หรือไม่ 🙂
imike


1

คุณสามารถใช้StringEx มันยาวยืดไปกับการแปลงสตริงกับจำนวนรวมStringtoDouble()

extension String {
    func toDouble() -> Double?
}

มันจะตรวจสอบสตริงและล้มเหลวหากไม่สามารถแปลงเป็นสองเท่า

ตัวอย่าง:

import StringEx

let str = "123.45678"
if let num = str.toDouble() {
    println("Number: \(num)")
} else {
    println("Invalid string")
}


0

ยังใช้งานได้:

// Init default Double variable
var scanned: Double()

let scanner = NSScanner(string: "String to Scan")
scanner.scanDouble(&scanned)

// scanned has now the scanned value if something was found.

หมายเหตุ: 'scanDouble' เลิกใช้แล้วใน iOS 13.0
uplearnedu.com


0

การใช้Scannerในบางกรณีเป็นวิธีที่สะดวกมากในการแยกตัวเลขออกจากสตริง และมันก็เกือบจะทรงพลังเช่นเดียวกับNumberFormatterเมื่อมันมาถึงการถอดรหัสและการจัดการกับรูปแบบตัวเลขและสถานที่ต่างๆ สามารถแยกตัวเลขและสกุลเงินด้วยตัวแยกทศนิยมและตัวแยกกลุ่ม

import Foundation
// The code below includes manual fix for whitespaces (for French case)
let strings = ["en_US": "My salary is $9,999.99",
               "fr_FR": "Mon salaire est 9 999,99€",
               "de_DE": "Mein Gehalt ist 9999,99€",
               "en_GB": "My salary is £9,999.99" ]
// Just for referce
let allPossibleDecimalSeparators = Set(Locale.availableIdentifiers.compactMap({ Locale(identifier: $0).decimalSeparator}))
print(allPossibleDecimalSeparators)
for str in strings {
    let locale = Locale(identifier: str.key)
    let valStr = str.value.filter{!($0.isWhitespace || $0 == Character(locale.groupingSeparator ?? ""))}
    print("Value String", valStr)

    let sc = Scanner(string: valStr)
    // we could do this more reliably with `filter` as well
    sc.charactersToBeSkipped = CharacterSet.decimalDigits.inverted
    sc.locale = locale

    print("Locale \(locale.identifier) grouping separator: |\(locale.groupingSeparator ?? "")| . Decimal separator: \(locale.decimalSeparator ?? "")")
    while !(sc.isAtEnd) {
        if let val = sc.scanDouble() {
            print(val)
        }

    }
}

อย่างไรก็ตามมีปัญหาเกี่ยวกับตัวคั่นที่อาจคิดว่าเป็นตัวคั่นคำ

// This doesn't work. `Scanner` just ignores grouping separators because scanner tends to seek for multiple values
// It just refuses to ignore spaces or commas for example.
let strings = ["en_US": "$9,999.99", "fr_FR": "9999,99€", "de_DE": "9999,99€", "en_GB": "£9,999.99" ]
for str in strings {
    let locale = Locale(identifier: str.key)
    let sc = Scanner(string: str.value)
    sc.charactersToBeSkipped = CharacterSet.decimalDigits.inverted.union(CharacterSet(charactersIn: locale.groupingSeparator ?? ""))
    sc.locale = locale
    print("Locale \(locale.identifier) grouping separator: \(locale.groupingSeparator ?? "") . Decimal separator: \(locale.decimalSeparator ?? "")")
    while !(sc.isAtEnd) {
        if let val = sc.scanDouble() {
            print(val)
        }

    }
}
//     sc.scanDouble(representation: Scanner.NumberRepresentation) could help if there were .currency case

ไม่มีปัญหาในการตรวจหาสถานที่อัตโนมัติ โปรดทราบว่าการจัดกลุ่มตัวแยกในภาษาฝรั่งเศสในสตริง "Mon salaire est 9 999,99 €" ไม่ใช่ช่องว่างแม้ว่ามันอาจแสดงผลเหมือนกับช่องว่าง (ที่นี่ไม่ใช่) นั่นเป็นสาเหตุที่รหัสด้านล่างทำงานได้ดีโดยไม่มี!$0.isWhitespaceการกรองอักขระ

let stringsArr = ["My salary is $9,999.99",
                  "Mon salaire est 9 999,99€",
                  "Mein Gehalt ist 9.999,99€",
                  "My salary is £9,999.99" ]

let tagger = NSLinguisticTagger(tagSchemes: [.language], options: Int(NSLinguisticTagger.Options.init().rawValue))
for str in stringsArr {
    tagger.string = str
    let locale = Locale(identifier: tagger.dominantLanguage ?? "en")
    let valStr = str.filter{!($0 == Character(locale.groupingSeparator ?? ""))}
    print("Value String", valStr)

    let sc = Scanner(string: valStr)
    // we could do this more reliably with `filter` as well
    sc.charactersToBeSkipped = CharacterSet.decimalDigits.inverted
    sc.locale = locale

    print("Locale \(locale.identifier) grouping separator: |\(locale.groupingSeparator ?? "")| . Decimal separator: \(locale.decimalSeparator ?? "")")
    while !(sc.isAtEnd) {
        if let val = sc.scanDouble() {
            print(val)
        }

    }
}
// Also will fail if groupingSeparator == decimalSeparator (but don't think it's possible)

-1

ฉันค้นหาเพิ่มเติมเพื่อเพิ่มส่วนขยายใน String ดังนี้

extension String {
    var doubleValue: Double {
        return (self as NSString).doubleValue
    }
}

แล้วคุณก็สามารถเขียนรหัสของคุณ:

myDouble = myString.doubleValue

-1

ปัญหาของฉันคือจุลภาคดังนั้นฉันแก้มันด้วยวิธีนี้:

extension String {
    var doubleValue: Double {
        return Double((self.replacingOccurrences(of: ",", with: ".") as NSString).doubleValue)
    }
}


-6

เราสามารถใช้ค่า CDouble ซึ่งจะได้รับจาก myString.doubleValue


ข้อผิดพลาด: 'String' ไม่มีสมาชิกชื่อ 'doubleValue'
Matthew Knippen

@Matthew ใช่ไม่มีสมาชิกชื่อ "double value" ดังนั้นเราจึงสามารถใช้ CDouble Value
ANIL.MUNDURU

1
en.wikipedia.org/wiki/ ...... อ้างถึงตัวเลขที่ซับซ้อนที่นั่นและอ่านเอกสารอ้างอิงของ Swift .. ไม่มี CD CD ... คุณกำลังพูดถึง Swift หรือภาษาอื่นหรือไม่? และฉันหมายถึงสวิฟท์ที่ไม่มีนามสกุล
Adrian Sluyters
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.