Runden Sie einen doppelten Wert schnell auf x Dezimalstellen


395

Kann mir jemand sagen, wie man einen Doppelwert in Swift auf x Dezimalstellen rundet?

Ich habe:

var totalWorkTimeInHours = (totalWorkTime/60/60)

Mit totalWorkTimeeinem NSTimeInterval (doppelt) auf dem zweiten Platz.

totalWorkTimeInHours wird mir die Stunden geben, aber es gibt mir die Zeit in einer so langen, genauen Zahl, z. B. 1,543240952039 ......

Wie runde ich dies beim Drucken auf beispielsweise 1,543 ab totalWorkTimeInHours?


1
Siehe meine Antwort zu finden bis zu 9 verschiedenen Möglichkeiten , um eine Doppel mit Darwin abzurunden round(_:), Double round(), NSStringinitializer, Stringinitializer, NumberFormatter, Doppel Verlängerung oder sogar NSDecimalNumberund Decimal.
Imanou Petit

@Rounded, ein schneller 5.1-Property-Wrapper: gist.github.com/abhijithpp/1cc41b41a5d1c8f007da90f20bc0c65f
Abhijith

Antworten:


389

Sie können die Swift- roundFunktion verwenden, um dies zu erreichen.

Um a Doublemit einer Genauigkeit von 3 Stellen zu runden , multiplizieren Sie es zuerst mit 1000, runden Sie es und dividieren Sie das gerundete Ergebnis durch 1000:

let x = 1.23556789
let y = Double(round(1000*x)/1000)
print(y)  // 1.236

Anders als jede Art von printf(...)oder String(format: ...)Lösungen ist das Ergebnis dieser Operation noch vom Typ Double.

EDIT:
In Bezug auf die Kommentare, dass es manchmal nicht funktioniert, lesen Sie bitte dies:

Was jeder Programmierer über Gleitkomma-Arithmetik wissen sollte


Aus einigen Gründen hilft es nicht. Ich verwende dies im folgenden Fall. TransformOf <Double, String> (von JSON: {Double (round (($ 0! Als NSString) .doubleValue * 100) / 100)}, toJSON: {"($ 0)"})
Fawkes

29
Funktioniert bei mir auf dem Spielplatz nicht: let rate = 9.94999999999; Double(round(rate * 100) / 100);Ausgabe: Funktioniert 9.94999999999, 9.949999999999999nur für den Druck, aber wie kann ich sie einer Variablen zuweisen?
Alexander Yakovlev

Sie sollten hierfür Dezimal verwenden, nicht einfache Doppel.
Csotiriou

13
"Was jeder Informatiker über Gleitkomma-Arithmetik wissen sollte" umfasst 73 Seiten. Was ist die TL; DR dazu? :)
JaredH

1
@ HardikDG Ich erinnere mich nicht, sorry :-)
Alexander Yakovlev

431

Erweiterung für Swift 2

Eine allgemeinere Lösung ist die folgende Erweiterung, die mit Swift 2 und iOS 9 funktioniert:

extension Double {
    /// Rounds the double to decimal places value
    func roundToPlaces(places:Int) -> Double {
        let divisor = pow(10.0, Double(places))
        return round(self * divisor) / divisor
    }
}


Erweiterung für Swift 3

In Swift 3 roundwird ersetzt durch rounded:

extension Double {
    /// Rounds the double to decimal places value
    func rounded(toPlaces places:Int) -> Double {
        let divisor = pow(10.0, Double(places))
        return (self * divisor).rounded() / divisor
    }
}


Beispiel, das Double auf 4 Dezimalstellen gerundet zurückgibt:

let x = Double(0.123456789).roundToPlaces(4)  // x becomes 0.1235 under Swift 2
let x = Double(0.123456789).rounded(toPlaces: 4)  // Swift 3 version

17
Die Natur von Swift's Double scheint zu sein, dass es ungenau sein kann - aufgrund der Art und Weise, wie es in Binärform gespeichert / abgerufen wird, wird selbst bei Verwendung dieser Rundungsfunktion keine auf 3 Dezimalstellen gerundete Zahl zurückgegeben: z . B. round(8.46 * pow(10.0, 3.0)) / pow(10.0, 3.0)Rückgabe 8.460000000000001. Dasselbe mit Float zu tun, zumindest in diesem Szenario , scheint tatsächlich zu funktionieren: round(Float(8.46) * pow(10.0, 3.0)) / pow(10.0, 3.0)Erträge 8.46. Nur etwas Bemerkenswertes.
Ben Saufley

2
Leider funktioniert dies nicht mehr in Swift 3, ich No '*' candidates produce the expected contextual result type 'FloatingPointRoundingRule'
erhalte

2
Ich habe die Lösung aktualisiert und eine Erweiterung für Swift 3 hinzugefügt.
Sebastian

2
Um schneller zu sein 3 ... sollten Sie für func abgerundet (toPlaces Orte: Int) -> Double
FouZ

2
@ BenSaufley Aber es funktioniert auch nicht, wenn Sie 98,68 eingeben. In diesem Fall bekomme ich 98.6800003
Alexander Khitev

340

Wie runde ich dies beim Drucken auf beispielsweise 1,543 ab totalWorkTimeInHours?

Um rund totalWorkTimeInHours3 Ziffern für das Drucken, verwenden Sie den StringKonstruktor , der eine nimmt formatstring:

print(String(format: "%.3f", totalWorkTimeInHours))

24
Das ist Abschneiden, nicht Runden
Augapfel

33
@ Augenball: Eigentlich macht es rund. Es ist das gleiche Verhalten wie bei der C printf-Funktionalität, die auf die angeforderten Ziffern rundet. Also String(format: "%.3f", 1.23489)druckt1.235
zisoft

6
Das Originalposter sucht nach einem zu verwendenden numerischen Wert und nicht nach einer anzuzeigenden Zeichenfolge.
pr1001

17
@ pr1001, vielleicht schon, aber das war damals noch nicht klar und 46 andere fanden meine Antwort nützlich. Stapelüberlauf ist mehr als nur eine Hilfe für das OP.
Vacawama

3
ungerade, dies gibt jedes Mal 0,00 zurück.
Eric H

254

Mit Swift 5 können Sie je nach Bedarf einen der 9 folgenden Stile auswählen , um ein abgerundetes Ergebnis aus a zu erhalten Double.


# 1. Mit FloatingPoint rounded()Methode

Im einfachsten Fall können Sie die Double rounded()Methode verwenden.

let roundedValue1 = (0.6844 * 1000).rounded() / 1000
let roundedValue2 = (0.6849 * 1000).rounded() / 1000
print(roundedValue1) // returns 0.684
print(roundedValue2) // returns 0.685

# 2. Mit FloatingPoint rounded(_:)Methode

let roundedValue1 = (0.6844 * 1000).rounded(.toNearestOrEven) / 1000
let roundedValue2 = (0.6849 * 1000).rounded(.toNearestOrEven) / 1000
print(roundedValue1) // returns 0.684
print(roundedValue2) // returns 0.685

#3. Verwenden der Darwin- roundFunktion

Foundation bietet eine roundFunktion über Darwin.

import Foundation

let roundedValue1 = round(0.6844 * 1000) / 1000
let roundedValue2 = round(0.6849 * 1000) / 1000
print(roundedValue1) // returns 0.684
print(roundedValue2) // returns 0.685

# 4. Verwenden einer Doublebenutzerdefinierten Erweiterungsmethode, die mit Darwin roundund powFunktionen erstellt wurde

Wenn Sie den vorherigen Vorgang viele Male wiederholen möchten, kann eine Umgestaltung Ihres Codes eine gute Idee sein.

import Foundation

extension Double {
    func roundToDecimal(_ fractionDigits: Int) -> Double {
        let multiplier = pow(10, Double(fractionDigits))
        return Darwin.round(self * multiplier) / multiplier
    }
}

let roundedValue1 = 0.6844.roundToDecimal(3)
let roundedValue2 = 0.6849.roundToDecimal(3)
print(roundedValue1) // returns 0.684
print(roundedValue2) // returns 0.685

# 5. Mit NSDecimalNumber rounding(accordingToBehavior:)Methode

Bietet bei Bedarf NSDecimalNumbereine ausführliche, aber leistungsstarke Lösung zum Runden von Dezimalzahlen.

import Foundation

let scale: Int16 = 3

let behavior = NSDecimalNumberHandler(roundingMode: .plain, scale: scale, raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: true)

let roundedValue1 = NSDecimalNumber(value: 0.6844).rounding(accordingToBehavior: behavior)
let roundedValue2 = NSDecimalNumber(value: 0.6849).rounding(accordingToBehavior: behavior)

print(roundedValue1) // returns 0.684
print(roundedValue2) // returns 0.685

# 6. Mit NSDecimalRound(_:_:_:_:)Funktion

import Foundation

let scale = 3

var value1 = Decimal(0.6844)
var value2 = Decimal(0.6849)

var roundedValue1 = Decimal()
var roundedValue2 = Decimal()

NSDecimalRound(&roundedValue1, &value1, scale, NSDecimalNumber.RoundingMode.plain)
NSDecimalRound(&roundedValue2, &value2, scale, NSDecimalNumber.RoundingMode.plain)

print(roundedValue1) // returns 0.684
print(roundedValue2) // returns 0.685

# 7. Mit NSString init(format:arguments:)initializer

Wenn Sie eine NSStringvon Ihrem Rundungsvorgang zurückgeben möchten , ist die Verwendung des NSStringInitialisierers eine einfache, aber effiziente Lösung.

import Foundation

let roundedValue1 = NSString(format: "%.3f", 0.6844)
let roundedValue2 = NSString(format: "%.3f", 0.6849)
print(roundedValue1) // prints 0.684
print(roundedValue2) // prints 0.685

# 8. Mit String init(format:_:)initializer

Swifts StringTyp ist mit der NSStringKlasse der Foundation verbunden . Daher können Sie den folgenden Code verwenden, um a Stringvon Ihrer Rundungsoperation zurückzugeben:

import Foundation

let roundedValue1 = String(format: "%.3f", 0.6844)
let roundedValue2 = String(format: "%.3f", 0.6849)
print(roundedValue1) // prints 0.684
print(roundedValue2) // prints 0.685

# 9. Verwenden vonNumberFormatter

Wenn Sie erwarten, eine String?von Ihrem Rundungsvorgang zu erhalten, NumberFormatterbietet eine hochgradig anpassbare Lösung.

import Foundation

let formatter = NumberFormatter()
formatter.numberStyle = NumberFormatter.Style.decimal
formatter.roundingMode = NumberFormatter.RoundingMode.halfUp
formatter.maximumFractionDigits = 3

let roundedValue1 = formatter.string(from: 0.6844)
let roundedValue2 = formatter.string(from: 0.6849)
print(String(describing: roundedValue1)) // prints Optional("0.684")
print(String(describing: roundedValue2)) // prints Optional("0.685")

1
Gute Antwort. Ich könnte auf # 5 vorschlagen, dass Sie die Verwendung in Betracht ziehen könnten Decimal, die gebührenfrei überbrückt ist NSDecimalNumber. Decimalist der Swift elegantere Unterstützung nativer Typ und Angebote für native Operatoren wie +, -etc.
Rob

@ Rob Ich habe meine Antwort mit NSDecimalRound(_:_:_:_:)Funktion aktualisiert . Vielen Dank.
Imanou Petit

Wenn Sie die Auswahl Nr. 9 verwenden, wird garantiert, dass Sie den festen Bruch (Anzahl der Präzisionsziffern) erwarten, sagen wir Dezimalzahl 43.12345 und Bruch = 6. Sie erhalten 43.123450
Almas Adilbek

1
@ImanouPetit Vielen Dank, dass Sie dies gepostet haben. Ich kann ein paar Erweiterungen nuklearisieren.
Adrian

Ich bin traurig, dass dies NumberFormatterdie letzte Option ist, während es die erste sein sollte, um Benutzern Zahlen zu präsentieren. Keine andere Methode generiert korrekt lokalisierte Zahlen.
Sulthan

93

In Swift 2.0 und Xcode 7.2:

let pi: Double = 3.14159265358979
String(format:"%.2f", pi)

Beispiel:

Geben Sie hier die Bildbeschreibung ein


50

Dies ist ein voll funktionsfähiger Code

Swift 3.0 / 4.0 / 5.0, Xcode 9.0 GM / 9.2 und höher

let doubleValue : Double = 123.32565254455
self.lblValue.text = String(format:"%.f", doubleValue)
print(self.lblValue.text)

Ausgabe - 123

let doubleValue : Double = 123.32565254455
self.lblValue_1.text = String(format:"%.1f", doubleValue)
print(self.lblValue_1.text)

Ausgabe - 123.3

let doubleValue : Double = 123.32565254455
self.lblValue_2.text = String(format:"%.2f", doubleValue)
print(self.lblValue_2.text)

Ausgabe - 123,33

let doubleValue : Double = 123.32565254455
self.lblValue_3.text = String(format:"%.3f", doubleValue)
print(self.lblValue_3.text)

Ausgabe - 123.326


1
eine Zeile?, scheint wie 3 Zeilen;)
Petter Friberg

Sie können Dinge nicht mit Strings berechnen, ich denke nicht, dass es eine richtige Antwort ist, weil es nur zum Anzeigen ist.
JBarros35

25

Aufbauend auf Yogis Antwort ist hier eine Swift-Funktion, die den Job erledigt:

func roundToPlaces(value:Double, places:Int) -> Double {
    let divisor = pow(10.0, Double(places))
    return round(value * divisor) / divisor
}

20

In Swift 3.0 und Xcode 8.0:

extension Double {
    func roundTo(places: Int) -> Double {
        let divisor = pow(10.0, Double(places))
        return (self * divisor).rounded() / divisor
    }
}

Verwenden Sie diese Erweiterung wie folgt:

let doubleValue = 3.567
let roundedValue = doubleValue.roundTo(places: 2)
print(roundedValue) // prints 3.56

19

Swift 4, Xcode 10

yourLabel.text =  String(format:"%.2f", yourDecimalValue)

1
Ich habe nicht abgelehnt, aber ich denke, der Grund könnte sein, dass dies eine Zeichenfolgendarstellung einer Zahl zurückgibt, nicht der Zahl. Was in Ordnung ist, wenn das alles ist, was Sie brauchen, aber Sie möchten vielleicht, dass die Zahl selbst für die weitere Verwendung abgerundet wird. Das OP hat "Wenn ich drucke" gesagt, daher denke ich, dass dies in diesem Fall eine akzeptable, einfache und saubere Lösung ist.
Ben Stahl

1
Perfekt. Einzeilige Lösung. Ich musste nur Dezimalwerte als Zeichenfolgen in meinen Beschriftungen anzeigen.
Zeeshan

18

Der Code für bestimmte Ziffern nach Dezimalstellen lautet:

var a = 1.543240952039
var roundedString = String(format: "%.3f", a)

Hier weist% .3f den Swift an, diese Zahl auf 3 Dezimalstellen zu runden. Wenn Sie eine doppelte Zahl wünschen, können Sie diesen Code verwenden:

// String zu verdoppeln

var roundedString = Double(String(format: "%.3f", b))


14

Verwenden Sie die integrierte Foundation Darwin-Bibliothek

SWIFT 3

extension Double {
    func round(to places: Int) -> Double {
        let divisor = pow(10.0, Double(places))
        return Darwin.round(self * divisor) / divisor
    }
}

Verwendungszweck:

let number:Double = 12.987654321
print(number.round(to: 3)) 

Ausgänge: 12.988


9

Ein praktischer Weg kann die Verwendung einer Erweiterung vom Typ Double sein

extension Double {
    var roundTo2f: Double {return Double(round(100 *self)/100)  }
    var roundTo3f: Double {return Double(round(1000*self)/1000) }
}

Verwendungszweck:

let regularPie:  Double = 3.14159
var smallerPie:  Double = regularPie.roundTo3f  // results 3.142
var smallestPie: Double = regularPie.roundTo2f  // results 3.14

9

Wenn Sie DoubleWerte runden möchten, möchten Sie möglicherweise Swift verwenden, Decimaldamit keine Fehler auftreten, die auftreten können, wenn Sie versuchen, mit diesen gerundeten Werten zu rechnen. Wenn Sie verwenden Decimal, kann es Dezimalwerte dieses gerundeten Gleitkommawerts genau darstellen.

So können Sie tun:

extension Double {
    /// Convert `Double` to `Decimal`, rounding it to `scale` decimal places.
    ///
    /// - Parameters:
    ///   - scale: How many decimal places to round to. Defaults to `0`.
    ///   - mode:  The preferred rounding mode. Defaults to `.plain`.
    /// - Returns: The rounded `Decimal` value.

    func roundedDecimal(to scale: Int = 0, mode: NSDecimalNumber.RoundingMode = .plain) -> Decimal {
        var decimalValue = Decimal(self)
        var result = Decimal()
        NSDecimalRound(&result, &decimalValue, scale, mode)
        return result
    }
}

Dann können Sie den gerundeten DecimalWert wie folgt erhalten:

let foo = 427.3000000002
let value = foo.roundedDecimal(to: 2) // results in 427.30

Wenn Sie es mit einer bestimmten Anzahl von Dezimalstellen anzeigen möchten (und die Zeichenfolge für das aktuelle Gebietsschema des Benutzers lokalisieren möchten), können Sie Folgendes verwenden NumberFormatter:

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

if let string = formatter.string(for: value) {
    print(string)
}

2
Die bisher beste Antwort.
Codetard

(4.81).roundedDecimal(to: 2, mode: .down)wird 4,8 statt 4,81 zurückgeben, Decimal(string: self.description)!für eine genaue verwendendecimalValue
vk.edward.li

1
@ vk.edward.li - Ja, man sollte vorsichtig sein, wenn es darum geht, Dezimalstellen nach oben / unten zu runden, da Werte wie 4,81 einfach nicht genau dargestellt werden können Double(es wird 4.8099999999999996). Ich würde jedoch von der Verwendung abraten description(da die verwendete Rundung nicht dokumentiert ist und Änderungen vorbehalten ist). Wenn Sie wirklich dezimalgenau rechnen möchten, sollten Sie dies Doublevollständig vermeiden und stattdessen Decimaldirekt verwenden (z . B. Decimal(sign: .plus, exponent: -2, significand: 481)oder Decimal(string: "4.81"). Aber nicht verwenden description.
Rob

@Rob Normalerweise ist es unmöglich, den Zeichenfolgenwert "4.81" zu erhalten, wenn er als Double gespeichert ist. Daher müssen Sie self.description (einen modifizierten Grisu2-Algorithmus) verwenden, um die bereits verlorene Genauigkeit zu
korrigieren

Ich verstehe deine Meinung. Ich bin einfach nicht einverstanden mit Ihrer Lösung. Das Rundungsverhalten der descriptionMethode ist weder dokumentiert noch garantiert. Außerdem ist es nicht lokalisiert. IMHO ist es ein Fehler, descriptionetwas anderes als Protokollierungszwecke zu verwenden. Ich würde entweder Decimaldurchgehend verwenden, ganz vermeiden Doubleoder einfach einen anderen Rundungsmodus verwenden. Wenn Sie müssen, verwenden Sie auch Ihre eigene lokalisierte Methode, die einen Algorithmus im Grisu-Stil verwendet (dies erscheint jedoch unnötig, wenn Sie wissen, wie viele Dezimalstellen Sie runden möchten). Aber ich würde es vermeiden, mich auf dieses Nebenverhalten von zu verlassen description.
Rob

8

Dies ist eine Art lange Problemumgehung, die sich als nützlich erweisen kann, wenn Ihre Anforderungen etwas komplexer sind. Sie können in Swift einen Zahlenformatierer verwenden.

let numberFormatter: NSNumberFormatter = {
    let nf = NSNumberFormatter()
    nf.numberStyle = .DecimalStyle
    nf.minimumFractionDigits = 0
    nf.maximumFractionDigits = 1
    return nf
}()

Angenommen, Ihre Variable, die Sie drucken möchten, ist

var printVar = 3.567

Dadurch wird sichergestellt, dass es im gewünschten Format zurückgegeben wird:

numberFormatter.StringFromNumber(printVar)

Das Ergebnis hier ist also "3.6" (gerundet). Dies ist zwar nicht die wirtschaftlichste Lösung, aber ich gebe sie an, weil das OP das Drucken erwähnte (in diesem Fall ist ein String nicht unerwünscht) und weil diese Klasse das Einstellen mehrerer Parameter ermöglicht.


1
Ein kurzer Hinweis, dass jeder Formatierer programmgesteuert ziemlich teuer ist, was ihn für Aufgaben, die schnell oder wiederholt ausgeführt werden müssen, schlecht beraten macht.
Jonathan Thornton

7

ich würde ... benutzen

print(String(format: "%.3f", totalWorkTimeInHours))

und ändern Sie .3f in eine beliebige Anzahl von Dezimalzahlen, die Sie benötigen


Er wollte mit 3 Ziffern drucken, nicht in NSTimeInterval
Mohsen Hossein für den

7

Entweder:

  1. Verwenden von String(format:):

    • Typecast Doubleto Stringmit %.3fFormatbezeichner und dann zurück zuDouble

      Double(String(format: "%.3f", 10.123546789))!
    • Oder erweitern Sie Double, um N-Dezimalstellen zu behandeln:

      extension Double {
          func rounded(toDecimalPlaces n: Int) -> Double {
              return Double(String(format: "%.\(n)f", self))!
          }
      }
  2. Nach Berechnung

    • mit 10 ^ 3 multiplizieren, runden und dann durch 10 ^ 3 dividieren ...

      (1000 * 10.123546789).rounded()/1000
    • Oder erweitern Sie Double, um N-Dezimalstellen zu behandeln:

      extension Double {    
          func rounded(toDecimalPlaces n: Int) -> Double {
              let multiplier = pow(10, Double(n))
              return (multiplier * self).rounded()/multiplier
          }
      }

6

Dies ist ein flexiblerer Algorithmus zum Runden auf N signifikante Stellen

Swift 3-Lösung

extension Double {
// Rounds the double to 'places' significant digits
  func roundTo(places:Int) -> Double {
    guard self != 0.0 else {
        return 0
    }
    let divisor = pow(10.0, Double(places) - ceil(log10(fabs(self))))
    return (self * divisor).rounded() / divisor
  }
}


// Double(0.123456789).roundTo(places: 2) = 0.12
// Double(1.23456789).roundTo(places: 2) = 1.2
// Double(1234.56789).roundTo(places: 2) = 1200

6

Der beste Weg, eine doppelte Eigenschaft zu formatieren, ist die Verwendung der vordefinierten Apple-Methoden.

mutating func round(_ rule: FloatingPointRoundingRule)

FloatingPointRoundingRule ist eine Aufzählung mit folgenden Möglichkeiten

Aufzählungsfälle:

Fall wegFromZero Runden Sie auf den nächsten zulässigen Wert, dessen Größe größer oder gleich der der Quelle ist.

Fall unten Runden Sie auf den nächsten zulässigen Wert ab, der kleiner oder gleich der Quelle ist.

Fall zu NearestOrAwayFromZero Runde auf den nächsten zulässigen Wert; Wenn zwei Werte gleich nahe beieinander liegen, wird der mit der größeren Größe gewählt.

Fall zu NearestOrEven Round auf den nächsten zulässigen Wert; Wenn zwei Werte gleich nahe beieinander liegen, wird der gerade gewählt.

Fall in Richtung Null Runden Sie auf den nächsten zulässigen Wert, dessen Größe kleiner oder gleich der der Quelle ist.

case up Runden Sie auf den nächsten zulässigen Wert, der größer oder gleich der Quelle ist.

var aNumber : Double = 5.2
aNumber.rounded(.up) // 6.0

6

Runden Sie einen Doppelwert auf x Dezimalzahl
NO. von Nachkommastellen

var x = 1.5657676754
var y = (x*10000).rounded()/10000
print(y)  // 1.5658 

var x = 1.5657676754 
var y = (x*100).rounded()/100
print(y)  // 1.57 

var x = 1.5657676754
var y = (x*10).rounded()/10
print(y)  // 1.6

Was ist los mit diesem Code? Was zeigen die drei Beispiele?
Rene

Nur-Code-Antworten sind nicht hilfreich. Bitte versuchen Sie zu erklären, was jedes dieser Beispiele bewirkt.
Moe

5

Nicht Swift, aber ich bin mir sicher, dass Sie auf die Idee kommen.

pow10np = pow(10,num_places);
val = round(val*pow10np) / pow10np;

4

Dies scheint in Swift 5 zu funktionieren.

Sehr überrascht, dass es dafür noch keine Standardfunktion gibt.

// Abschneiden von Doppel- auf n-Dezimalstellen mit Rundung

extension Double {

    func truncate(to places: Int) -> Double {
    return Double(Int((pow(10, Double(places)) * self).rounded())) / pow(10, Double(places))
    }

}

2

Sie können diese Erweiterung hinzufügen:

extension Double {
    var clean: String {
        return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(format: "%.2f", self)
    }
}

und nenne es so:

let ex: Double = 10.123546789
print(ex.clean) // 10.12

Dies ist eine nette Implementierung der Darstellung als String. Ich frage mich, ob es möglich oder vernünftig ist, eine Erweiterung der Darstellung der Anzahl der Ziffern nach dem Zeitraum zu schreiben, der immer noch als Double beibehalten wird.
denkt schnell

2

Verwenden Sie Decimal, um Float-Fehler zu vermeiden

extension Float {
    func rounded(rule: NSDecimalNumber.RoundingMode, scale: Int) -> Float {
        var result: Decimal = 0
        var decimalSelf = NSNumber(value: self).decimalValue
        NSDecimalRound(&result, &decimalSelf, scale, rule)
        return (result as NSNumber).floatValue
    }
}

Ex.
1075,58 Runden auf 1075,57 bei Verwendung von Float mit Skalierung: 2 und .down
1075,58 Runden auf 1075,58 bei Verwendung von Decimal mit Skalierung: 2 und .down


1

Ich habe mich gefragt, ob es möglich ist, die Eingabe eines Benutzers zu korrigieren. Das heißt, wenn sie drei Dezimalstellen anstelle von zwei für einen Dollarbetrag eingeben. Sagen Sie 1.111 statt 1.11. Können Sie das Problem durch Runden beheben? Die Antwort lautet aus vielen Gründen nein! Mit Geld würde alles über 0,001 irgendwann Probleme in einem echten Scheckheft verursachen.

Hier ist eine Funktion, um die Benutzereingabe nach dem Zeitraum auf zu viele Werte zu überprüfen. Aber was erlaubt 1., 1.1 und 1.11.

Es wird davon ausgegangen, dass der Wert bereits auf erfolgreiche Konvertierung von einem String in einen Double überprüft wurde.

//func need to be where transactionAmount.text is in scope

func checkDoublesForOnlyTwoDecimalsOrLess()->Bool{


    var theTransactionCharacterMinusThree: Character = "A"
    var theTransactionCharacterMinusTwo: Character = "A"
    var theTransactionCharacterMinusOne: Character = "A"

    var result = false

    var periodCharacter:Character = "."


    var myCopyString = transactionAmount.text!

    if myCopyString.containsString(".") {

         if( myCopyString.characters.count >= 3){
                        theTransactionCharacterMinusThree = myCopyString[myCopyString.endIndex.advancedBy(-3)]
         }

        if( myCopyString.characters.count >= 2){
            theTransactionCharacterMinusTwo = myCopyString[myCopyString.endIndex.advancedBy(-2)]
        }

        if( myCopyString.characters.count > 1){
            theTransactionCharacterMinusOne = myCopyString[myCopyString.endIndex.advancedBy(-1)]
        }


          if  theTransactionCharacterMinusThree  == periodCharacter {

                            result = true
          }


        if theTransactionCharacterMinusTwo == periodCharacter {

            result = true
        }



        if theTransactionCharacterMinusOne == periodCharacter {

            result = true
        }

    }else {

        //if there is no period and it is a valid double it is good          
        result = true

    }

    return result


}

1
//find the distance between two points
let coordinateSource = CLLocation(latitude: 30.7717625, longitude:76.5741449 )
let coordinateDestination = CLLocation(latitude: 29.9810859, longitude: 76.5663599)
let distanceInMeters = coordinateSource.distance(from: coordinateDestination)
let valueInKms = distanceInMeters/1000
let preciseValueUptoThreeDigit = Double(round(1000*valueInKms)/1000)
self.lblTotalDistance.text = "Distance is : \(preciseValueUptoThreeDigit) kms"

1
extension String{
  var roundedValue:String {
     return String(format: "%.3f", self)
}}

Verwendungszweck :

totalWorkTimeInHours.roundedValue

1

Hier ist eine für SwiftUI, wenn Sie ein Textelement mit dem Zahlenwert benötigen.

struct RoundedDigitText : View {
    let digits : Int
    let number : Double

    var body : some View {
        Text(String(format: "%.\(digits)f", number))
    }
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.