Szybkie podwójne do sznurka


108

Zanim zaktualizowałem xCode 6, nie miałem problemów z rzutowaniem double na ciąg, ale teraz wyświetla mi się błąd

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

Daje mi komunikat o błędzie „double nie da się zamienić na łańcuch”. Czy jest na to inny sposób?


5
Przydatne może być również zdefiniowanie tego w następujący sposóbvar b = "\(a)"
— erdekhayser

Odpowiedzi:


211

Nie jest rzutowaniem, ale tworzeniem łańcucha z wartości o określonym formacie.

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

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

W innym formacie:

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

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

Możesz również pominąć tę formatwłaściwość, jeśli formatowanie nie jest potrzebne.


1
A co z podwójnym z większą liczbą cyfr ułamkowych? Na przykład niech a = 2.34934340320 let stringValue = String (format: "% f", a) da 2.349343
— Nico

1
Wyświetlaniem można sterować za pomocą opcji formatowania printf, patrz: Specyfikatory formatu ciągu i printf (3) .
— zaph

2
Po prostu trzeba zmienić format, aby kontrolować ilość cyfr: format:"%.1f" = 1 digit // 1.5; format:"%.5f" = 5 digits // 1.50000
— Megaetron,

3
Zaktualizuj swoją odpowiedź, w Swift 2.1 po prostu musisz to zrobić String(yourDouble).
— Alexandre G.

1
Możesz użyć let zamiast var. Nie ma teraz potrzeby, aby dzwonić do tego kilka razy.
— Oleksandr

81
let double = 1.5 
let string = double.description

zaktualizuj Xcode 7.1 • Swift 2.1:

Teraz Double można również zamienić na String, więc możesz go po prostu używać, jak chcesz:

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

Swift 3 lub nowszy możemy rozszerzyć LosslessStringConvertiblei uczynić go ogólnym

Xcode 11.3 • Swift 5.1 lub nowszy

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

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

Dla ustalonej liczby cyfr ułamkowych możemy rozszerzyć FloatingPointprotokół:

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

Jeśli potrzebujesz większej kontroli nad formatem liczb (minimalne i maksymalne cyfry ułamkowe oraz tryb zaokrąglania), możesz użyć 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
czy to hack, czy jest to legalny sposób, aby to zrobić? czy spowodowałoby to jakieś problemy z różnymi wersjami iOS?
— Esqarrouth

2
Nie, nie będziesz mieć żadnych problemów z różnymi wersjami iOS. Działa również na OSX. BTW to właśnie otrzymujesz, wykonując interpolację ciągów za pomocą Double lub Int.
— Leo Dabus

Bardzo przydatne. Nie możesz formatować jak% f. Działa również dla Int, więc masz jeden sposób na zrobienie tego dla dwóch typów.
— Patrik Vaberer

To nie zadziała dla 0,00001, zmieni się na „1e-05” jako ciąg.
— Alex

Wymienić String(format: "%.\(digits)f", self as! CVarArg)zString(format: "%.*f", digits, self as! CVarArg)
— rmaddy

21

Oprócz odpowiedzi @Zaph możesz tworzyć extension:

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

Stosowanie:

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

1
@MaximShoustin OP nie ma wystarczającej liczby przedstawicieli, aby głosować i odpowiadać, 15 jest wymaganych. Nie zgadzam się też z tworzeniem Rozszerzenia, gdy stwierdzenie: a.toString()zobaczy inny programista, na pewno będzie moment WTF.
— zaph

1
@Zaph dlaczego nie. Na pewno możesz dodać jakiś prefiks i zmienić go, myToString()aby mieć pewność, że jest to niestandardowa definicja. Ale podobnie jak w innych językach, prototypowanie prowadzi do uniknięcia powielania kodu i dobrej konserwacji.
— Maxim Shoustin

@MaximShoustin newbie question: jaka jest różnica między println("output: \(a.toString())")i println("output: \(a)"). Druga opcja nie powoduje błędów kompilacji. Czy ta opcja jest złą praktyką?
— Alex Guerrero

Czy istnieje sprytny sposób na napisanie takiego rozszerzenia Double lub FloatingPoint, które działałoby na opcjonalnym Double, aby zwrócić pusty ciąg?
— Kinergy

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

11

Swift 3+: wypróbuj ten wiersz kodu

let num: Double = 1.5

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

9

aby coś stało się ciągiem w swift, z wyjątkiem być może wartości wyliczeniowych, po prostu zrób to, co robisz w metodzie println ()

na przykład:

var stringOfDBL = "\(myDouble)"


3

Ta funkcja umożliwia określenie liczby miejsc dziesiętnych do wyświetlenia:

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

Stosowanie:

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

Wymienić String(format:"%."+numberOfDecimalPlaces.description+"f", number)zString(format:"%.*f", numberOfDecimalPlaces, number)
— rmaddy

3

Istnieje wiele odpowiedzi, które sugerują różne techniki. Ale podczas prezentowania liczb w interfejsie użytkownika zawsze chcesz użyć znaku a, NumberFormatteraby wyniki były odpowiednio sformatowane, zaokrąglone i zlokalizowane:

let value = 10000.5

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

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

Jeśli chcesz mieć stałą liczbę miejsc dziesiętnych, np. Dla wartości walut

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

Ale piękno tego podejścia polega na tym, że będzie ono odpowiednio zlokalizowane, co spowoduje, że w 10,000.50USA, ale 10.000,50w Niemczech. Różne lokalizacje mają różne preferowane formaty liczb i powinniśmy pozwolić na NumberFormatterużycie formatu preferowanego przez użytkownika końcowego podczas prezentowania wartości liczbowych w interfejsie użytkownika.

Nie trzeba dodawać, że chociaż NumberFormatterjest niezbędny podczas przygotowywania reprezentacji ciągów w interfejsie użytkownika, nie powinien być używany w przypadku zapisywania wartości liczbowych jako ciągów do trwałego przechowywania, interfejsu z usługami sieciowymi itp.


2
To powinno być oznaczone jako prawidłowa odpowiedź
— Asad Khan



0
var b = String(stringInterpolationSegment: a)

To działa dla mnie. Możesz spróbować


0

W Swift 4, jeśli chcesz modyfikować i używać Double w interfejsie użytkownika jako textLabel „String”, możesz dodać to na końcu swojego pliku:

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

}

I użyj tego w ten sposób, jeśli chcesz mieć to na etykiecie tekstowej:

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

Lub wydrukuj jako Int:

print(weatherData.tempCelsius.roundToInt())

0

Wolałbym podejście NSNumber i NumberFormatter (w razie potrzeby), a także możesz użyć rozszerzenia, aby uniknąć wzdęcia kodu

extension Double {

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

}

Możesz również potrzebować odwrotnego podejścia

extension String {

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

}

dlaczego zwracasz opcjonalne, ale przypisujesz .nan, jeśli nil? Powinieneś zrobić jedno lub drugie. Nie obie. Przy okazji, co złego w używaniu inicjatora String? Możesz także uczynić go bardziej ogólnym rozszerzającym LossLessStringConvertibleprotokołem zamiast rozszerzania Double extension LosslessStringConvertible { var string: String { return .init(self) } }
— Leo Dabus

Czy masz rację powracając Double? To odmowa, ponieważ już sprawdzam, czy jest zero i
— zwracam

0

Swift 5 : Użyj następującego kodu

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

Wymienić String(format: "%.\(points)f", self)zString(format: "%.*f", points, self)
— rmaddy
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.