Cepat dua kali lipat menjadi string

108

Sebelum saya memperbarui xCode 6, saya tidak memiliki masalah dalam mentransmisikan dobel ke string tetapi sekarang memberi saya kesalahan

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

Ini memberi saya pesan kesalahan "double is not convertible to string". Apakah ada cara lain untuk melakukannya?

tim_yng
sumber
5
Mungkin juga berguna untuk mendefinisikannya sepertivar b = "\(a)"
erdekhayser

Jawaban:

211

Itu tidak mentransmisikan, itu membuat string dari nilai dengan format.

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

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

Dengan format yang berbeda:

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

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

Anda juga dapat menghilangkan formatproperti jika tidak diperlukan pemformatan.

zaph
sumber
1
Bagaimana dengan rangkap dengan bilangan pecahan yang lebih besar? Seperti biarkan a = 2.34934340320 biarkan stringValue = String (format: "% f", a) akan menghasilkan 2.349343
Nico
1
Tampilan dapat dikontrol dengan opsi format printf, lihat: String Format Specifiers dan printf (3) .
zaf
2
Anda hanya perlu mengubah format Anda untuk mengontrol jumlah digit: format:"%.1f" = 1 digit // 1.5; format:"%.5f" = 5 digits // 1.50000
Megaetron
3
Harap perbarui jawaban Anda, di Swift 2.1 yang perlu Anda lakukan String(yourDouble).
Alexandre G.
1
Anda dapat menggunakan let, bukan var. Sekarang tidak perlu memanggilnya beberapa kali.
Oleksandr
81
let double = 1.5 
let string = double.description

perbarui Xcode 7.1 • Swift 2.1:

Sekarang Double juga dapat diubah menjadi String sehingga Anda dapat menggunakannya sesuai keinginan:

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

Swift 3 atau yang lebih baru dapat kita perpanjang LosslessStringConvertibledan membuatnya menjadi generik

Xcode 11.3 • Swift 5.1 atau lebih baru

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

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

Untuk sejumlah digit pecahan yang tetap, kami dapat memperluas FloatingPointprotokol:

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

Jika Anda membutuhkan lebih banyak kontrol atas format angka Anda (digit pecahan minimum dan maksimum dan mode pembulatan) Anda dapat menggunakan 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"
Leo Dabus
sumber
1
apakah ini hack atau cara yang sah untuk melakukannya? apakah itu akan menyebabkan masalah dengan versi ios yang berbeda?
Esqarrouth
2
Tidak, Anda tidak akan mengalami masalah dengan versi iOS yang berbeda. Ini juga berfungsi untuk OSX. BTW inilah yang Anda dapatkan saat melakukan Interpolasi String dengan Double atau Int.
Leo Dabus
Sangat berguna. Anda tidak dapat memformat seperti% f. Dan itu bekerja juga untuk Int jadi Anda punya satu cara untuk melakukannya untuk dua jenis.
Patrik Vaberer
Ini tidak akan bekerja untuk 0,00001, ini menjadi "1e-05" sebagai string.
Alex
Ganti String(format: "%.\(digits)f", self as! CVarArg)denganString(format: "%.*f", digits, self as! CVarArg)
rmaddy
21

Selain jawaban @Zaph, Anda dapat membuat extension:

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

Pemakaian:

var a:Double = 1.5
println("output: \(a.toString())")  // output: 1.5
Maxim Shoustin
sumber
1
@MaximShoustin OP tidak memiliki cukup perwakilan untuk memberikan suara dan menjawab, 15 diperlukan. Saya juga tidak setuju dengan pembuatan Extension, padahal pernyataan: a.toString()dilihat oleh developer lain pasti ada momen WTF.
zaf
1
@Aph mengapa tidak. Untuk memastikan Anda dapat menambahkan beberapa awalan dan mengubahnya myToString()untuk memastikan bahwa definisi kustomnya. Tetapi seperti dalam bahasa lain, pembuatan prototipe mengarah pada menghindari duplikasi kode dan pemeliharaan yang baik.
Maxim Shoustin
@MaximShoustin pertanyaan pemula: apa perbedaan antara println("output: \(a.toString())")dan println("output: \(a)"). Opsi kedua tidak menyebabkan kesalahan kompilasi. Apakah opsi ini praktik yang buruk?
Alex Guerrero
Apakah ada cara cerdas untuk menulis ekstensi seperti itu ke Double atau FloatingPoint yang akan bekerja pada Double Opsional untuk mengembalikan String kosong?
Kinergy
@KinNyatayourDouble?.toString() ?? ""
Leo Dus
11

Swift 3+: Coba baris kode ini

let num: Double = 1.5

let str = String(format: "%.2f", num)
Shiv Kumar
sumber
9

untuk membuat apapun menjadi string dengan cepat kecuali mungkin nilai enum cukup lakukan apa yang Anda lakukan di metode println ()

sebagai contoh:

var stringOfDBL = "\(myDouble)"
eric bob
sumber
3

Swift 4 : Gunakan kode berikut

let number = 2.4
let string = String(format: "%.2f", number)
Abhishek Jain
sumber
1
Ini solusi yang sama seperti yang diberikan oleh @ shiv-kumar stackoverflow.com/a/46487485/2227743
Eric Aya
3

Fungsi ini memungkinkan Anda menentukan jumlah tempat desimal yang akan ditampilkan:

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

Pemakaian:

let numberString = doubleToStringDecimalPlacesWithDouble(number: x, numberOfDecimalPlaces: 2)
MobileMon
sumber
Gantikan String(format:"%."+numberOfDecimalPlaces.description+"f", number)denganString(format:"%.*f", numberOfDecimalPlaces, number)
rmaddy
3

Ada banyak jawaban di sini yang menyarankan berbagai teknik. Namun saat menyajikan angka di UI, Anda selalu ingin menggunakan a NumberFormatteragar hasilnya diformat dengan benar, dibulatkan, dan dilokalkan:

let value = 10000.5

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

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

Jika Anda ingin jumlah tempat desimal tetap, misalnya untuk nilai mata uang

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

Tapi keindahan dari pendekatan ini, adalah bahwa itu akan dilokalkan dengan benar, menghasilkan di 10,000.50AS tetapi 10.000,50di Jerman. Lokal yang berbeda memiliki format pilihan yang berbeda untuk angka, dan kita harus membiarkanNumberFormatter menggunakan format yang disukai oleh pengguna akhir saat menyajikan nilai numerik dalam UI.

Tak perlu dikatakan, walaupun NumberFormatterpenting saat menyiapkan representasi string dalam UI, itu tidak boleh digunakan jika menulis nilai numerik sebagai string untuk penyimpanan persisten, antarmuka dengan layanan web, dll.

rampok
sumber
2
Ini harus ditandai sebagai jawaban yang benar
Asad Khan
2

Dalam 3 cepat:

var a: Double = 1.5
var b: String = String(a)
carlson
sumber
1

Di swift 3 itu sederhana seperti yang diberikan di bawah ini

let stringDouble =  String(describing: double)
Sebin Roy
sumber
3
Ini mengembalikan misalnya "Optional(6.1696108999999995)"untuk saya.
McSullivan D'Ander
0
var b = String(stringInterpolationSegment: a)

Ini berhasil untuk saya. Anda mungkin bisa mencobanya

sevenkplus
sumber
0

Di Swift 4 jika Anda ingin memodifikasi dan menggunakan Double di UI sebagai "String" textLabel, Anda dapat menambahkan ini di akhir file:

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

}

Dan gunakan seperti ini jika Anda ingin memilikinya dalam label teks:

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

Atau cetak sebagai Int:

print(weatherData.tempCelsius.roundToInt())
Patrik Rikama-Hinnenberg
sumber
0

Saya lebih suka pendekatan NSNumber dan NumberFormatter (di mana perlu), juga u dapat menggunakan ekstensi untuk menghindari kode kembung

extension Double {

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

}

Anda juga bisa membutuhkan pendekatan terbalik

extension String {

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

}
Giuseppe Mazzilli
sumber
mengapa Anda mengembalikan opsional tetapi menetapkan .nan jika nil? Anda harus melakukan salah satunya. Tidak keduanya. Btw Apa yang salah dengan menggunakan penginisialisasi String? Anda juga dapat membuatnya menjadi LossLessStringConvertibleprotokol perluasan yang lebih umum daripada memperpanjang Double extension LosslessStringConvertible { var string: String { return .init(self) } }
Leo Dabus
U benar mengembalikan Double? Apakah menolak karena saya sudah memeriksanya nihil dan mengembalikan NaN
Giuseppe Mazzilli
0

Cepat 5 : Gunakan kode berikut

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)
    }
}
g212gs
sumber
Gantikan String(format: "%.\(points)f", self)denganString(format: "%.*f", points, self)
rmaddy