Swift kép thành chuỗi


108

Trước khi tôi cập nhật xCode 6, tôi không gặp vấn đề gì khi truyền một đôi sang một chuỗi nhưng bây giờ nó báo cho tôi một lỗi

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

Nó cung cấp cho tôi thông báo lỗi "double không thể chuyển đổi thành chuỗi". CÒn cách nào khác để thực hiện việc này không?


5
Nó cũng có thể hữu ích để chỉ định nghĩa nó nhưvar b = "\(a)"
erdekhayser

Câu trả lời:


211

Nó không phải là truyền, nó đang tạo một chuỗi từ một giá trị có định dạng.

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

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

Với một định dạng khác:

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

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

Bạn cũng có thể bỏ qua thuộc formattính nếu không cần định dạng.


1
Điều gì về một đôi với một số chữ số phân số lớn hơn? Giống như let a = 2.34934340320 let stringValue = String (định dạng: "% f", a) sẽ cho kết quả là 2.349343
Nico

1
Màn hình có thể được điều khiển bằng các tùy chọn định dạng printf, xem: Bộ định dạng chuỗiprintf (3) .
zaph

2
Bạn chỉ cần phải thay đổi định dạng của bạn để kiểm soát số lượng chữ số: format:"%.1f" = 1 digit // 1.5; format:"%.5f" = 5 digits // 1.50000
Megaetron

3
Vui lòng cập nhật câu trả lời của bạn, trong Swift 2.1, bạn chỉ cần làm String(yourDouble).
Alexandre G.

1
Bạn có thể sử dụng let thay vì var. Bây giờ không cần phải gọi nó nhiều lần.
Oleksandr

81
let double = 1.5 
let string = double.description

cập nhật Xcode 7.1 • Swift 2.1:

Bây giờ Double cũng có thể chuyển đổi thành Chuỗi để bạn có thể đơn giản sử dụng nó như bạn muốn:

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

Swift 3 trở lên, chúng tôi có thể mở rộng LosslessStringConvertiblevà làm cho nó chung chung

Xcode 11.3 • Swift 5.1 trở lên

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

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

Đối với một số phân số cố định, chúng tôi có thể mở rộng FloatingPointgiao thức:

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

Nếu bạn cần kiểm soát nhiều hơn đối với định dạng số của mình (chữ số phân số tối thiểu và tối đa và chế độ làm tròn), bạn có thể sử dụng 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
Đây là một cuộc tấn công hay đây là một cách hợp pháp để làm điều đó? nó sẽ gây ra bất kỳ vấn đề với các phiên bản ios khác nhau?
Esqarrouth

2
Không, bạn sẽ không gặp vấn đề gì với các phiên bản ios khác nhau. Nó cũng hoạt động cho OSX. BTW đây là những gì bạn nhận được khi thực hiện Nội suy chuỗi với một Double hoặc Int.
Leo Dabus

Rất hữu ích. Bạn không thể định dạng như% f. Và Nó cũng hoạt động cho Int vì vậy bạn có một cách để làm điều đó cho hai loại.
Patrik Vaberer

Điều này sẽ không hoạt động cho 0,00001, nó trở thành "1e-05" dưới dạng một chuỗi.
Alex

Thay thế String(format: "%.\(digits)f", self as! CVarArg)vớiString(format: "%.*f", digits, self as! CVarArg)
rmaddy

21

Ngoài câu trả lời @Zaph, bạn có thể tạo extension:

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

Sử dụng:

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

1
@MaximShoustin OP không có đủ đại diện để bỏ phiếu và trả lời, cần phải có 15 người. Tôi cũng không đồng ý với việc tạo một Tiện ích mở rộng, khi tuyên bố: a.toString()được nhìn thấy bởi một nhà phát triển khác chắc chắn sẽ có một khoảnh khắc WTF.
zaph

1
@Zaph tại sao không. Để chắc chắn, bạn có thể thêm một số tiền tố và thay đổi nó để myToString()chắc chắn rằng định nghĩa tùy chỉnh của nó. Nhưng giống như trong các ngôn ngữ khác, việc tạo mẫu giúp tránh trùng lặp mã và bảo trì tốt.
Maxim Shoustin

@MaximShoustin câu hỏi dành cho người mới: sự khác biệt giữa println("output: \(a.toString())")println("output: \(a)"). Tùy chọn thứ hai không gây ra lỗi biên dịch. Tùy chọn này có phải là một thực tiễn xấu?
Alex Guerrero

Có cách nào thông minh để viết một phần mở rộng như vậy cho Double hoặc FloatingPoint sẽ hoạt động trên Double tùy chọn để trả về một Chuỗi trống không?
Kinergy

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

11

Swift 3+: Hãy thử những dòng mã này

let num: Double = 1.5

let str = String(format: "%.2f", num)

9

để tạo bất kỳ thứ gì thành chuỗi nhanh chóng ngoại trừ các giá trị enum có thể chỉ cần thực hiện những gì bạn làm trong phương thức println ()

ví dụ:

var stringOfDBL = "\(myDouble)"


3

Hàm này sẽ cho phép bạn chỉ định số vị trí thập phân để hiển thị:

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

Sử dụng:

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

Thay thế String(format:"%."+numberOfDecimalPlaces.description+"f", number)vớiString(format:"%.*f", numberOfDecimalPlaces, number)
rmaddy

3

Có rất nhiều câu trả lời ở đây đề xuất một loạt các kỹ thuật. Nhưng khi trình bày các số trong giao diện người dùng, bạn luôn muốn sử dụng một NumberFormatterđể kết quả được định dạng, làm tròn và bản địa hóa đúng cách:

let value = 10000.5

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

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

Nếu bạn muốn cố định số vị trí thập phân, ví dụ: đối với giá trị tiền tệ

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

Nhưng cái hay của phương pháp này là nó sẽ được bản địa hóa một cách hợp lý, kết quả là ở 10,000.50Mỹ nhưng 10.000,50ở Đức. Các ngôn ngữ khác nhau có các định dạng ưu tiên khác nhau cho số và chúng ta nên NumberFormattersử dụng định dạng được người dùng cuối ưa thích khi trình bày các giá trị số trong giao diện người dùng.

Không cần phải nói, mặc dù NumberFormatterrất cần thiết khi chuẩn bị các biểu diễn chuỗi trong giao diện người dùng, nhưng nó không nên được sử dụng nếu viết các giá trị số dưới dạng chuỗi để lưu trữ liên tục, giao diện với các dịch vụ web, v.v.


2
Đây nên được đánh dấu là câu trả lời đúng
Asad Khan

2

Trong nhanh 3:

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

1

Trong swift 3, nó đơn giản như dưới đây

let stringDouble =  String(describing: double)

3
Điều này trả về ví dụ "Optional(6.1696108999999995)"cho tôi.
McSullivan D'Ander

0
var b = String(stringInterpolationSegment: a)

Điều này làm việc cho tôi. Bạn có thể thử


0

Trong Swift 4, nếu bạn muốn sửa đổi và sử dụng Double trong UI dưới dạng textLabel "String", bạn có thể thêm cái này vào cuối tệp của mình:

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

}

Và sử dụng nó như thế này nếu bạn muốn có nó trong textlabel:

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

Hoặc in nó dưới dạng Int:

print(weatherData.tempCelsius.roundToInt())

0

Tôi thích cách tiếp cận NSNumber và NumberFormatter (nếu cần), bạn cũng có thể sử dụng tiện ích mở rộng để tránh mã đầy hơi

extension Double {

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

}

Bạn cũng có thể cần cách tiếp cận ngược lại

extension String {

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

}

tại sao bạn trả về tùy chọn nhưng lại gán .nan if nil? Bạn nên làm một trong hai. Không phải cả hai. Btw Có gì sai khi sử dụng trình khởi tạo chuỗi? Bạn cũng có thể làm cho nó chung chung hơn mở rộng LossLessStringConvertiblegiao thức thay vì mở rộng đúp extension LosslessStringConvertible { var string: String { return .init(self) } }
Leo Dabus

Bạn đang phải trở lại Double? Là một từ chối vì tôi đã kiểm tra xem nó là con số không và trở về NaN
Giuseppe Mazzilli

0

Swift 5 : Sử dụng mã sau

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)
    }
}

Thay thế String(format: "%.\(points)f", self)vớiString(format: "%.*f", points, self)
rmaddy
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.