สวิฟต์สองครั้งเป็นสตริง


108

ก่อนที่ฉันจะอัปเดต xCode 6 ฉันไม่มีปัญหาในการส่งคู่เป็นสตริง แต่ตอนนี้ฉันมีข้อผิดพลาด

var a: Double = 1.5
var b: String = String(a)

มันทำให้ฉันมีข้อความแสดงข้อผิดพลาด "double is not convertible to string" มีวิธีอื่นที่จะทำได้หรือไม่?


5
นอกจากนี้ยังอาจมีประโยชน์ในการกำหนดเช่นvar b = "\(a)"
erdekhayser

คำตอบ:


212

ไม่ใช่การแคสต์ แต่เป็นการสร้างสตริงจากค่าที่มีรูปแบบ

let a: Double = 1.5
let b: String = String(format: "%f", a)

print("b: \(b)") // b: 1.500000

ด้วยรูปแบบอื่น:

let c: String = String(format: "%.1f", a)

print("c: \(c)") // c: 1.5

คุณยังสามารถละเว้นformatคุณสมบัติได้หากไม่จำเป็นต้องจัดรูปแบบ


1
แล้วคู่ที่มีเลขเศษส่วนใหญ่กว่าล่ะ? เช่นให้ a = 2.34934340320 ให้ stringValue = String (รูปแบบ: "% f", a) จะให้ 2.349343
Nico

1
จอแสดงผลสามารถควบคุมได้ด้วย printf การจัดรูปแบบตัวเลือกดู: ตัวระบุรูปแบบสตริงและprintf (3)
zaph

2
คุณต้องเปลี่ยนรูปแบบของคุณเพื่อควบคุมจำนวนตัวเลข: format:"%.1f" = 1 digit // 1.5; format:"%.5f" = 5 digits // 1.50000
Megaetron

3
โปรดอัปเดตคำตอบของคุณในสวิฟท์ 2.1 String(yourDouble)คุณก็ต้องทำ
Alexandre G.

1
คุณสามารถใช้ let แทน var ตอนนี้ไม่จำเป็นต้องเรียกมันหลายครั้ง
Oleksandr

82
let double = 1.5 
let string = double.description

อัปเดต Xcode 7.1 • Swift 2.1:

ตอนนี้ Double สามารถแปลงเป็น String ได้ดังนั้นคุณสามารถใช้งานได้ตามที่คุณต้องการ:

let double = 1.5
let doubleString = String(double)   // "1.5"

Swift 3 หรือใหม่กว่าเราสามารถขยายLosslessStringConvertibleและทำให้เป็นแบบทั่วไปได้

Xcode 11.3 • Swift 5.1 หรือใหม่กว่า

extension LosslessStringConvertible { 
    var string: String { .init(self) } 
}

let double = 1.5 
let string = double.string  //  "1.5"

สำหรับตัวเลขเศษส่วนคงที่เราสามารถขยายFloatingPointโปรโตคอล:

extension FloatingPoint {
    func fixedFraction(digits: Int) -> String {
        return String(format: "%.*f", digits, self as! CVarArg)
    }
}

หากคุณต้องการควบคุมรูปแบบตัวเลขของคุณมากขึ้น (ตัวเลขเศษส่วนต่ำสุดและสูงสุดและโหมดการปัดเศษ) คุณสามารถใช้ NumberFormatter:

extension Formatter {
    static let number = NumberFormatter()
}

extension FloatingPoint {
    func fractionDigits(min: Int = 2, max: Int = 2, roundingMode: NumberFormatter.RoundingMode = .halfEven) -> String {
        Formatter.number.minimumFractionDigits = min
        Formatter.number.maximumFractionDigits = max
        Formatter.number.roundingMode = roundingMode
        Formatter.number.numberStyle = .decimal
        return Formatter.number.string(for: self) ?? ""
    }
}

2.12345.fractionDigits()                                    // "2.12"
2.12345.fractionDigits(min: 3, max: 3, roundingMode: .up)   // "2.124"

1
นี่เป็นการแฮ็กหรือเป็นวิธีที่ถูกต้องหรือไม่ มันจะทำให้เกิดปัญหากับ ios เวอร์ชันต่างๆหรือไม่
Esqarrouth

2
ไม่คุณจะไม่มีปัญหากับ iOS เวอร์ชันต่างๆ นอกจากนี้ยังใช้ได้กับ OSX BTW นี่คือสิ่งที่คุณจะได้รับเมื่อทำการแก้ไขสตริงด้วย Double หรือ Int
Leo Dabus

มีประโยชน์มาก. คุณไม่สามารถจัดรูปแบบเหมือน% f และยังใช้ได้กับ Int ดังนั้นคุณจึงมีวิธีหนึ่งที่จะทำได้สองประเภท
Patrik Vaberer

สิ่งนี้ใช้ไม่ได้กับ 0.00001 กลายเป็น "1e-05" เป็นสตริง
Alex

แทนที่String(format: "%.\(digits)f", self as! CVarArg)ด้วยString(format: "%.*f", digits, self as! CVarArg)
rmaddy

21

นอกจากคำตอบ @Zaph แล้วคุณสามารถสร้างไฟล์ extension:

extension Double {
    func toString() -> String {
        return String(format: "%.1f",self)
    }
}

การใช้งาน:

var a:Double = 1.5
println("output: \(a.toString())")  // output: 1.5

1
@MaximShoustin OP ไม่มีตัวแทนเพียงพอที่จะโหวตและตอบต้องมี 15 คน ฉันไม่เห็นด้วยกับการสร้างส่วนขยายเมื่อคำสั่ง: a.toString()นักพัฒนารายอื่นเห็นว่าจะมีช่วงเวลา WTF แน่นอน
zaph

1
@ ซาฟทำไมไม่. แน่นอนว่าคุณสามารถเพิ่มคำนำหน้าและเปลี่ยนmyToString()เป็นคำจำกัดความที่กำหนดเองได้ แต่เช่นเดียวกับในภาษาอื่น ๆ การสร้างต้นแบบนำไปสู่การหลีกเลี่ยงรหัสซ้ำและการบำรุงรักษาที่ดี
Maxim Shoustin

@MaximShoustin คำถามมือใหม่: อะไรคือความแตกต่างระหว่างprintln("output: \(a.toString())")และprintln("output: \(a)"). ตัวเลือกที่สองไม่ก่อให้เกิดข้อผิดพลาดในการคอมไพล์ ตัวเลือกนี้เป็นการปฏิบัติที่ไม่ดีหรือไม่?
Alex Guerrero

มีวิธีที่ชาญฉลาดในการเขียนส่วนขยายดังกล่าวไปยัง Double หรือ FloatingPoint ที่จะทำงานบน Optional Double เพื่อส่งคืน String ว่างหรือไม่?
Kinergy

@KinergyyourDouble?.toString() ?? ""
Leo Dabus


9

เพื่อสร้างสตริงใด ๆ อย่างรวดเร็วยกเว้นค่า enum เพียงแค่ทำสิ่งที่คุณทำในเมธอด println ()

ตัวอย่างเช่น:

var stringOfDBL = "\(myDouble)"


3

ฟังก์ชันนี้จะช่วยให้คุณระบุจำนวนตำแหน่งทศนิยมที่จะแสดง:

func doubleToString(number:Double, numberOfDecimalPlaces:Int) -> String {
    return String(format:"%."+numberOfDecimalPlaces.description+"f", number)
}

การใช้งาน:

let numberString = doubleToStringDecimalPlacesWithDouble(number: x, numberOfDecimalPlaces: 2)

แทนที่String(format:"%."+numberOfDecimalPlaces.description+"f", number)ด้วยString(format:"%.*f", numberOfDecimalPlaces, number)
rmaddy

3

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

let value = 10000.5

let formatter = NumberFormatter()
formatter.numberStyle = .decimal

guard let string = formatter.string(for: value) else { return }
print(string) // 10,000.5

หากคุณต้องการจำนวนตำแหน่งทศนิยมคงที่เช่นค่าสกุลเงิน

let value = 10000.5

let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.maximumFractionDigits = 2
formatter.minimumFractionDigits = 2

guard let string = formatter.string(for: value) else { return }
print(string) // 10,000.50

แต่ความสวยงามของแนวทางนี้ก็คือมันจะถูกแปลอย่างถูกต้องซึ่งส่งผลให้เกิดใน10,000.50สหรัฐอเมริกา แต่10.000,50ในเยอรมนี สถานที่ต่างๆมีรูปแบบที่ต้องการสำหรับตัวเลขที่แตกต่างกันและเราควรปล่อยให้NumberFormatterใช้รูปแบบที่ผู้ใช้ปลายทางต้องการเมื่อนำเสนอค่าตัวเลขภายใน UI

ไม่จำเป็นต้องพูดในขณะที่NumberFormatterมีความสำคัญในการเตรียมการแสดงสตริงภายใน UI แต่ก็ไม่ควรใช้หากเขียนค่าตัวเลขเป็นสตริงสำหรับพื้นที่จัดเก็บถาวรอินเทอร์เฟซกับบริการบนเว็บเป็นต้น


2
สิ่งนี้ควรถูกทำเครื่องหมายว่าเป็นคำตอบที่ถูกต้อง
Asad Khan




0

ใน Swift 4 หากคุณต้องการแก้ไขและใช้ Double ใน UI เป็น textLabel "String" คุณสามารถเพิ่มสิ่งนี้ได้ที่ท้ายไฟล์ของคุณ:

    extension Double {
func roundToInt() -> Int{
    return Int(Darwin.round(self))
}

}

และใช้สิ่งนี้หากคุณต้องการให้มีใน textlabel:

currentTemp.text = "\(weatherData.tempCelsius.roundToInt())"

หรือพิมพ์เป็น Int:

print(weatherData.tempCelsius.roundToInt())

0

ฉันต้องการแนวทาง NSNumber และ NumberFormatter (ที่ต้องการ) นอกจากนี้คุณสามารถใช้ส่วนขยายเพื่อหลีกเลี่ยงรหัสท้องอืด

extension Double {

   var toString: String {
      return NSNumber(value: self).stringValue
   }

}

คุณยังต้องการวิธีการย้อนกลับ

extension String {

    var toDouble: Double {
        return Double(self) ?? .nan
    }

}

ทำไมคุณถึงส่งคืนทางเลือก แต่กำหนด. nan ถ้าไม่มี? คุณควรทำอย่างใดอย่างหนึ่ง ไม่ใช่ทั้งสองอย่าง Btw มีอะไรผิดปกติกับการใช้ String initializer? นอกจากนี้คุณยังสามารถสร้างLossLessStringConvertibleโปรโตคอลการขยายแบบทั่วไปแทนการขยาย Double extension LosslessStringConvertible { var string: String { return .init(self) } }
Leo Dabus

คุณกำลังกลับมาเป็นคู่? เป็นการปฏิเสธเนื่องจากฉันตรวจสอบแล้วว่าเป็นศูนย์และส่งคืน NaN
Giuseppe Mazzilli

0

Swift 5 : ใช้รหัสต่อไปนี้

extension Double {

    func getStringValue(withFloatingPoints points: Int = 0) -> String {
        let valDouble = modf(self)
        let fractionalVal = (valDouble.1)
        if fractionalVal > 0 {
            return String(format: "%.*f", points, self)
        }
        return String(format: "%.0f", self)
    }
}

แทนที่String(format: "%.\(points)f", self)ด้วยString(format: "%.*f", points, self)
rmaddy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.