Swift Double to String

108

Bevor ich xCode 6 aktualisiert habe, hatte ich keine Probleme, ein Double in einen String umzuwandeln, aber jetzt gibt es einen Fehler

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

Es gibt mir die Fehlermeldung "double ist nicht in string konvertierbar". Gibt es eine andere Möglichkeit, dies zu tun?

tim_yng
quelle
5
Es kann auch nützlich sein, es einfach so zu definieren wievar b = "\(a)"
erdekhayser

Antworten:

211

Es wird nicht umgewandelt, sondern eine Zeichenfolge aus einem Wert mit einem Format erstellt.

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

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

Mit einem anderen Format:

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

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

Sie können die formatEigenschaft auch weglassen, wenn keine Formatierung erforderlich ist.

zaph
quelle
1
Was ist mit einem Doppel mit einer größeren Bruchzahl? Wie let a = 2.34934340320 let stringValue = String (Format: "% f", a) ergibt 2.349343
Nico
1
Die Anzeige kann mit den Formatierungsoptionen für printf gesteuert werden, siehe: String Format Specifiers und printf (3) .
Zaph
2
Sie müssen nur Ihr Format ändern, um die Anzahl der Ziffern zu steuern : format:"%.1f" = 1 digit // 1.5; format:"%.5f" = 5 digits // 1.50000
Megaetron
3
Bitte aktualisieren Sie Ihre Antwort, in Swift 2.1 müssen Sie nur noch tun String(yourDouble).
Alexandre G.
1
Sie können let anstelle von var verwenden. Es ist jetzt nicht nötig, es mehrmals aufzurufen.
Oleksandr
81
let double = 1.5 
let string = double.description

Update Xcode 7.1 • Swift 2.1:

Jetzt kann Double auch in String konvertiert werden, sodass Sie es einfach nach Ihren Wünschen verwenden können:

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

Swift 3 oder höher wir erweitern LosslessStringConvertibleund generisch machen

Xcode 11.3 • Swift 5.1 oder höher

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

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

Für eine feste Anzahl von Bruchstellen können wir das FloatingPointProtokoll erweitern:

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

Wenn Sie mehr Kontrolle über Ihr Zahlenformat benötigen (minimale und maximale Bruchstellen und Rundungsmodus), können Sie NumberFormatter verwenden:

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
quelle
1
Ist das ein Hack oder ist das ein legitimer Weg, es zu tun? Würde es Probleme mit verschiedenen iOS-Versionen verursachen?
Esqarrouth
2
Nein, Sie werden keine Probleme mit verschiedenen iOS-Versionen haben. Es funktioniert auch für OSX. Übrigens erhalten Sie dies, wenn Sie eine String-Interpolation mit einem Double oder einem Int durchführen.
Leo Dabus
Sehr hilfreich. Sie können nicht wie% f formatieren. Und es funktioniert auch für Int, so dass Sie eine Möglichkeit haben, dies für zwei Typen zu tun.
Patrik Vaberer
Dies funktioniert nicht für 0.00001, sondern wird als Zeichenfolge zu "1e-05".
Alex
Ersetzen Sie String(format: "%.\(digits)f", self as! CVarArg)durchString(format: "%.*f", digits, self as! CVarArg)
rmaddy
21

Zusätzlich zur @ Zaph-Antwort können Sie erstellen extension:

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

Verwendung:

var a:Double = 1.5
println("output: \(a.toString())")  // output: 1.5
Maxim Shoustin
quelle
1
@MaximShoustin Das OP hat nicht genügend Repräsentanten, um abzustimmen und zu antworten. 15 sind erforderlich. Ich bin auch nicht damit einverstanden, eine Erweiterung zu erstellen, wenn die Aussage: a.toString()von einem anderen Entwickler gesehen wird, wird es definitiv einen WTF-Moment geben.
Zaph
1
@ Zaph warum nicht. Natürlich können Sie ein Präfix hinzufügen und es ändern myToString(), um sicherzustellen, dass es eine benutzerdefinierte Definition hat. Aber wie in anderen Sprachen führt das Prototyping dazu, dass Code-Duplikate und eine gute Wartung vermieden werden.
Maxim Shoustin
@ MaximShoustin Neuling Frage: Was ist der Unterschied zwischen println("output: \(a.toString())")und println("output: \(a)"). Die zweite Option verursacht keine Kompilierungsfehler. Ist diese Option eine schlechte Praxis?
Alex Guerrero
Gibt es eine clevere Möglichkeit, eine solche Erweiterung in Double oder FloatingPoint zu schreiben, die bei einem optionalen Double funktioniert, um einen leeren String zurückzugeben?
Kinergy
@KinergyyourDouble?.toString() ?? ""
Leo Dabus
11

Swift 3+: Probieren Sie diese Codezeile aus

let num: Double = 1.5

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

Um irgendetwas schnell zu einem String zu machen, außer vielleicht Enum-Werten, machen Sie einfach das, was Sie in der println () -Methode tun

beispielsweise:

var stringOfDBL = "\(myDouble)"
Eric Bob
quelle
3

Swift 4 : Verwenden Sie den folgenden Code

let number = 2.4
let string = String(format: "%.2f", number)
Abhishek Jain
quelle
1
Es ist die gleiche Lösung wie die von @ shiv-kumar stackoverflow.com/a/46487485/2227743
Eric Aya
3

Mit dieser Funktion können Sie die Anzahl der anzuzeigenden Dezimalstellen angeben:

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

Verwendung:

let numberString = doubleToStringDecimalPlacesWithDouble(number: x, numberOfDecimalPlaces: 2)
MobileMon
quelle
Ersetzen Sie String(format:"%."+numberOfDecimalPlaces.description+"f", number)durchString(format:"%.*f", numberOfDecimalPlaces, number)
rmaddy
3

Hier gibt es viele Antworten, die eine Vielzahl von Techniken vorschlagen. Wenn Sie jedoch Zahlen in der Benutzeroberfläche anzeigen, möchten Sie ausnahmslos a verwenden, NumberFormatterdamit die Ergebnisse ordnungsgemäß formatiert, gerundet und lokalisiert werden:

let value = 10000.5

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

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

Wenn Sie eine feste Anzahl von Dezimalstellen wünschen, z. B. für Währungswerte

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

Das Schöne an diesem Ansatz ist jedoch, dass er ordnungsgemäß lokalisiert wird, was 10,000.50in den USA, aber 10.000,50in Deutschland zur Folge hat. Verschiedene Gebietsschemas haben unterschiedliche bevorzugte Formate für Zahlen, und wir sollten NumberFormatterdas vom Endbenutzer bevorzugte Format verwenden, wenn numerische Werte in der Benutzeroberfläche angezeigt werden.

Es ist unnötig zu erwähnen, dass dies NumberFormatterbei der Erstellung von Zeichenfolgendarstellungen in der Benutzeroberfläche von entscheidender Bedeutung ist. Es sollte jedoch nicht verwendet werden, wenn numerische Werte als Zeichenfolgen für die dauerhafte Speicherung, die Schnittstelle zu Webdiensten usw. geschrieben werden.

rauben
quelle
2
Dies sollte als die richtige Antwort markiert werden
Asad Khan
2

In schnellem 3:

var a: Double = 1.5
var b: String = String(a)
Carlson
quelle
1

In Swift 3 ist es einfach wie unten angegeben

let stringDouble =  String(describing: double)
Sebin Roy
quelle
3
Dies kehrt zB "Optional(6.1696108999999995)"für mich zurück.
McSullivan D'Ander
0
var b = String(stringInterpolationSegment: a)

Das funktioniert bei mir. Sie können es versuchen

siebenkplus
quelle
0

Wenn Sie in Swift 4 ein Double in der Benutzeroberfläche als textLabel "String" ändern und verwenden möchten, können Sie dies am Ende Ihrer Datei hinzufügen:

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

}}

Und verwenden Sie es so, wenn Sie es in einem Textlabel haben möchten:

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

Oder drucken Sie es als Int:

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

Ich würde den NSNumber- und NumberFormatter-Ansatz bevorzugen (wo nötig). Außerdem können Sie die Erweiterung verwenden, um ein Aufblähen des Codes zu vermeiden

extension Double {

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

}

Sie können auch einen umgekehrten Ansatz benötigen

extension String {

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

}
Giuseppe Mazzilli
quelle
Warum geben Sie optional zurück, weisen aber .nan zu, wenn nil? Sie sollten entweder das eine oder das andere tun. Nicht beide. Übrigens, was ist falsch an der Verwendung des String-Initialisierers? Sie können das LossLessStringConvertibleProtokoll auch generischer erweitern , anstatt Double extension LosslessStringConvertible { var string: String { return .init(self) } }
Leo Dabus am
Du hast Recht, Double zurückzugeben? Ist ein Müll, da ich bereits überprüfe, dass es Null ist und NaN
Giuseppe Mazzilli
0

Swift 5 : Verwenden Sie den folgenden Code

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
quelle
Ersetzen Sie String(format: "%.\(points)f", self)durchString(format: "%.*f", points, self)
rmaddy