Szybkie zaokrąglanie podwójnej wartości do liczby x miejsc dziesiętnych

395

Czy ktoś może mi powiedzieć, jak zaokrąglić podwójną wartość do x liczby miejsc dziesiętnych w Swift?

Mam:

var totalWorkTimeInHours = (totalWorkTime/60/60)

Z totalWorkTimebycia NSTimeInterval (dwukrotnie) na drugim.

totalWorkTimeInHours da mi godziny, ale da mi tyle czasu w tak długiej, precyzyjnej liczbie, np. 1,543240952039 ......

Jak zaokrąglić to w dół, powiedzmy, 1,543 podczas drukowania totalWorkTimeInHours?

Leighton
źródło
1
Zobacz moją odpowiedź , aby znaleźć się na 9 różnych sposobów przy użyciu podwójnej rundzie Darwin round(_:), Double round(), NSStringinicjator, Stringinicjująca, NumberFormatter, podwójne rozszerzenie lub nawet NSDecimalNumberi Decimal.
Imanou Petit,
@Rounded, otoki Swift 5.1 nieruchomości: gist.github.com/abhijithpp/1cc41b41a5d1c8f007da90f20bc0c65f
Abhijith

Odpowiedzi:

389

roundAby tego dokonać, możesz użyć funkcji Swift .

Aby zaokrąglić a Doublez dokładnością 3 cyfr, najpierw pomnóż ją przez 1000, zaokrągl ją i podziel zaokrąglony wynik przez 1000:

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

Inne niż jakiekolwiek rozwiązania printf(...)lub String(format: ...)rozwiązania, wynik tej operacji jest nadal tego samego typu Double.

EDYCJA:
Jeśli chodzi o komentarze, że czasami nie działa, przeczytaj to:

Co każdy programista powinien wiedzieć o arytmetyki zmiennoprzecinkowej

zisoft
źródło
Z niektórych powodów to nie pomaga. Używam tego w następującym przypadku TransformOf <Podwójny, ciąg> (fromJSON: {Podwójny (okrągły ((0 USD! Jako NSString) .doubleValue * 100) / 100)}, do JSON: {"(0 $)"})
Fawkes
29
Nie działa na mnie na placu zabaw: let rate = 9.94999999999; Double(round(rate * 100) / 100);Wyjście: 9.94999999999, 9.949999999999999działa tylko w przypadku wydruku, ale jak mogę przypisać go do zmiennej?
Alexander Yakovlev,
W tym celu powinieneś użyć Decimal, a nie zwykłych Doubles.
csotiriou,
13
„Co każdy informatyk powinien wiedzieć o arytmetyki zmiennoprzecinkowej” ma 73 strony. Co to jest za TL; DR? :)
JaredH
1
@HardikDG Nie pamiętam, przepraszam :-)
Alexander Yakovlev
430

Rozszerzenie do Swift 2

Bardziej ogólnym rozwiązaniem jest następujące rozszerzenie, które działa z Swift 2 i iOS 9:

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


Rozszerzenie do Swift 3

W Swift 3 roundotrzymuje brzmienie 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
    }
}


Przykład, który zwraca Podwójne zaokrąglone do 4 miejsc po przecinku:

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
Sebastian
źródło
17
Charakter Swift's Double wydaje się być taki, że może być nieprecyzyjny - ze względu na sposób przechowywania / dostępu w formacie binarnym nawet użycie tej funkcji zaokrąglania nie zwróci liczby zaokrąglonej do 3 miejsc po przecinku: np . round(8.46 * pow(10.0, 3.0)) / pow(10.0, 3.0)Zwraca 8.460000000000001. Robienie tego samego z Float, przynajmniej w tym scenariuszu , w rzeczywistości wydaje się działać: round(Float(8.46) * pow(10.0, 3.0)) / pow(10.0, 3.0)plony 8.46. Po prostu coś wartego odnotowania.
Ben Saufley,
2
Niestety nie działa to już w Swift 3, No '*' candidates produce the expected contextual result type 'FloatingPointRoundingRule'
pojawia
2
Zaktualizowałem rozwiązanie i dodałem rozszerzenie do Swift 3.
Sebastian
2
Aby być bardziej szybkim 3 ... powinieneś zmienić na func zaokrąglone (toPlaces miejsc: Int) -> Double
FouZ
2
@BenSaufley Ale to również nie działa, jeśli wpiszesz 98,68. W tym przypadku otrzymuję 98,6800003
Alexander Khitev
340

Jak zaokrąglić to w dół, powiedzmy, 1,543 podczas drukowania totalWorkTimeInHours ?

Aby zaokrąglić totalWorkTimeInHoursdo 3 cyfr w celu wydrukowania, użyj Stringkonstruktora, który pobiera formatciąg znaków:

print(String(format: "%.3f", totalWorkTimeInHours))
vacawama
źródło
24
To jest obcięcie, a nie zaokrąglenie
gałka oczna
33
@Eyeball: Właściwie to się kręci. Jest to takie samo zachowanie, jak funkcja C printf, która zaokrągla do żądanych cyfr. Więc String(format: "%.3f", 1.23489)drukuje1.235
zisoft,
6
Oryginalny plakat szuka wartości liczbowej do użycia, a nie ciągu do wyświetlenia.
pr1001
17
@ pr1001, być może tak, ale wówczas nie było to jasne, a 46 innych osób uznało moją odpowiedź za przydatną. Przepełnienie stosu to coś więcej niż tylko pomoc OP.
vacawama,
3
dziwne, to zwraca 0,00 za każdym razem.
Eric H
254

Z Swift 5, w zależności od potrzeb, możesz wybrać jeden z 9 następujących stylów , aby uzyskać zaokrąglony wynik od Double.


# 1. Przy użyciu FloatingPoint rounded()metody

W najprostszym przypadku możesz użyć tej Double rounded()metody.

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. Przy użyciu FloatingPoint rounded(_:)metody

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. Korzystanie z roundfunkcji Darwin

Fundacja oferuje roundfunkcję za pośrednictwem Darwina.

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. Korzystanie z Doubleniestandardowej metody rozszerzenia zbudowanej za pomocą Darwina roundi powfunkcji

Jeśli chcesz powtórzyć poprzednią operację wiele razy, dobrym pomysłem może być refaktoryzacja kodu.

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. Przy użyciu NSDecimalNumber rounding(accordingToBehavior:)metody

W razie potrzeby NSDecimalNumberoferuje pełne, ale potężne rozwiązanie do zaokrąglania liczb dziesiętnych.

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. Korzystanie z NSDecimalRound(_:_:_:_:)funkcji

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. Korzystanie z NSString init(format:arguments:)inicjalizatora

Jeśli chcesz zwrócić wynik NSStringz operacji zaokrąglania, użycie NSStringinicjatora jest prostym, ale wydajnym rozwiązaniem.

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. Korzystanie z String init(format:_:)inicjalizatora

StringTyp Swift jest połączony z NSStringklasą Foundation . Dlatego możesz użyć następującego kodu, aby zwrócić wynik Stringoperacji zaokrąglania:

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. Za pomocąNumberFormatter

Jeśli spodziewasz się, że skorzystasz String?z operacji zaokrąglania, NumberFormatteroferuje wysoce konfigurowalne rozwiązanie.

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")
Imanou Petit
źródło
1
Świetna odpowiedź. Mogę zasugerować na nr 5, że możesz rozważyć użycie Decimal, który jest bezpłatny do mostu NSDecimalNumber. DecimalPochodzi rodzaj i oferty Swift bardziej elegancki wsparcie dla rodzimych operatorów, takich jak +, -itp
Rob
@Rob Zaktualizowałem swoją odpowiedź NSDecimalRound(_:_:_:_:)funkcją. Dzięki.
Imanou Petit,
Korzystanie z wyboru nr 9 zagwarantuje, że będziesz oczekiwać stałej frakcji (liczby cyfr precyzyjnych), powiedzmy, że liczba dziesiętna 43.12345 i ułamek = 6, otrzymasz 43.123450
Almas
1
@ImanouPetit Dziękujemy za opublikowanie tego. Mogę nuke kilka rozszerzeń.
Adrian
Przykro mi, że NumberFormatterto ostatnia opcja, podczas gdy powinna być pierwsza do prezentowania liczb użytkownikom. Żadna inna metoda nie generuje poprawnie zlokalizowanych liczb.
Sulthan
93

W Swift 2.0 i Xcode 7.2:

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

Przykład:

wprowadź opis zdjęcia tutaj

Claudio Guirunas
źródło
50

To jest w pełni działający kod

Swift 3.0 / 4.0 / 5.0, Xcode 9.0 GM / 9.2 i nowsze

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

wyjście - 123

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

wyjście - 123,3

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

wyjście - 123,33

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

wyjście - 123.326

Krunal Patel
źródło
1
jedna linia ?, wydaje się jak 3 linie;)
Petter Friberg
nie można obliczyć rzeczy za pomocą ciągów, nie sądzę, że jest to poprawna odpowiedź, ponieważ służy tylko do wyświetlania.
JBarros35
25

Opierając się na odpowiedzi Jogina, oto funkcja Swift, która wykonuje to zadanie:

func roundToPlaces(value:Double, places:Int) -> Double {
    let divisor = pow(10.0, Double(places))
    return round(value * divisor) / divisor
}
Popiół
źródło
20

W Swift 3.0 i Xcode 8.0:

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

Użyj tego rozszerzenia tak:

let doubleValue = 3.567
let roundedValue = doubleValue.roundTo(places: 2)
print(roundedValue) // prints 3.56
jaiswal Rajan
źródło
19

Swift 4, Xcode 10

yourLabel.text =  String(format:"%.2f", yourDecimalValue)
Naishta
źródło
1
Nie przegłosowałem, ale myślę, że powodem może być to, że zwraca ciąg znaków reprezentujący liczbę, a nie liczbę. To dobrze, jeśli to wszystko, czego potrzebujesz, ale możesz chcieć zaokrąglić samą liczbę do dalszego użycia. OP powiedział „kiedy drukuję”, więc myślę, że w tym przypadku jest to akceptowalne, łatwe i czyste rozwiązanie.
Ben Stahl
1
Doskonały. Rozwiązanie jednoliniowe. Musiałem tylko pokazać wartości dziesiętne jako ciągi w moich etykietach.
zeeshan
18

Kod dla określonych cyfr po przecinku to:

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

Tutaj% .3f mówi szybkiemu, aby ta liczba została zaokrąglona do 3 miejsc po przecinku. A jeśli chcesz podwójną liczbę, możesz użyć tego kodu:

// String to Double

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

Ramazan Karami
źródło
14

Skorzystaj z wbudowanej biblioteki Foundation Darwin

SWIFT 3

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

Stosowanie:

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

Wyjścia: 12,988

George Filippakos
źródło
9

Przydatnym sposobem może być użycie rozszerzenia typu Double

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

Stosowanie:

let regularPie:  Double = 3.14159
var smallerPie:  Double = regularPie.roundTo3f  // results 3.142
var smallestPie: Double = regularPie.roundTo2f  // results 3.14
Marco Leong
źródło
9

Jeśli chcesz zaokrąglić Doublewartości, możesz użyć Swift, Decimalaby nie wprowadzać żadnych błędów, które mogą pojawić się podczas próby obliczenia matematycznego za pomocą tych zaokrąglonych wartości. Jeśli używasz Decimal, może dokładnie reprezentować wartości dziesiętne tej zaokrąglonej wartości zmiennoprzecinkowej.

Możesz więc zrobić:

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

Następnie możesz uzyskać zaokrągloną Decimalwartość w następujący sposób:

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

A jeśli chcesz wyświetlić go z określoną liczbą miejsc dziesiętnych (a także zlokalizować ciąg dla bieżących ustawień narodowych użytkownika), możesz użyć NumberFormatter:

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

if let string = formatter.string(for: value) {
    print(string)
}
Obrabować
źródło
2
Najlepsza jak dotąd odpowiedź.
Codetard
(4.81).roundedDecimal(to: 2, mode: .down)zwróci 4,8 zamiast 4,81, użyj Decimal(string: self.description)!do dokładnegodecimalValue
vk.edward.li
1
@ vk.edward.li - Tak, należy uważać na zaokrąglanie ułamków dziesiętnych w górę / w dół, ponieważ wartości takich jak 4.81 po prostu nie można dokładnie przedstawić Double(staje się 4.8099999999999996). Ale odradzam używanie description(ponieważ zaokrąglanie, które stosuje, nie jest udokumentowane i może ulec zmianie). Jeśli naprawdę chcesz robić matematykę z dokładnością dziesiętną, powinieneś unikać Doublecałkowicie i zamiast tego powinieneś używać Decimalbezpośrednio (np . Decimal(sign: .plus, exponent: -2, significand: 481)Lub Decimal(string: "4.81"). Ale nie używaj description.
Rob
@Rob zwykle nie można uzyskać wartości ciągu „4,81”, jeśli jest przechowywany jako Double, więc musisz użyć self.description (zmodyfikowany algorytm Grisu2), aby naprawić utratę
precyzji
Rozumiem twój punkt widzenia. Po prostu nie zgadzam się z twoim rozwiązaniem. Zaokrąglanie descriptionmetody nie jest ani udokumentowane, ani gwarantowane. Ponadto nie jest zlokalizowany. IMHO, błędem jest używanie descriptiondo celów innych niż logowanie. Albo używałbym Decimalcałego, unikając używania Doublecałkowicie, albo po prostu używałbym innego trybu zaokrąglania. Lub, jeśli musisz, użyj własnej zlokalizowanej metody wykorzystującej algorytm w stylu Grisu (ale wydaje się to niepotrzebne, gdy wiesz, ile miejsc po przecinku chcesz zaokrąglić). Ale unikałbym polegania na tym pomocniczym zachowaniu description.
Rob
8

Jest to rodzaj długiego obejścia, które może się przydać, jeśli Twoje potrzeby są nieco bardziej złożone. Możesz użyć formatera liczb w Swift.

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

Załóżmy, że twoja zmienna, którą chcesz wydrukować, to

var printVar = 3.567

Zapewni to, że zostanie zwrócony w żądanym formacie:

numberFormatter.StringFromNumber(printVar)

Wynik będzie więc wynosić „3,6” (w zaokrągleniu). Chociaż nie jest to najbardziej ekonomiczne rozwiązanie, daję to, ponieważ OP wspomniało o drukowaniu (w którym to przypadku String nie jest niepożądany) i ponieważ ta klasa pozwala na ustawienie wielu parametrów.

Inkidu616
źródło
1
Szybka uwaga, że ​​każdy formatyzator jest dość drogi programowo, co sprawia, że ​​nie jest zalecany do zadań, które muszą być wykonywane szybko lub powtarzalnie.
Jonathan Thornton,
7

użyłbym

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

i zmień .3f na dowolną liczbę potrzebnych liczb dziesiętnych

Mohsen Hossein pour
źródło
Chciał wydrukować 3 cyfry, aby nie dostać go w NSTimeInterval
Mohsen Hossein wlać
7

Zarówno:

  1. Używanie String(format:):

    • Typecast Doubledo Stringze %.3fspecyfikatorem formatu, a następnie z powrotem doDouble

      Double(String(format: "%.3f", 10.123546789))!
    • Lub rozszerz, Doubleaby obsłużyć miejsca N-dziesiętne:

      extension Double {
          func rounded(toDecimalPlaces n: Int) -> Double {
              return Double(String(format: "%.\(n)f", self))!
          }
      }
  2. Według obliczeń

    • pomnożyć przez 10 ^ 3, zaokrąglić, a następnie podzielić przez 10 ^ 3 ...

      (1000 * 10.123546789).rounded()/1000
    • Lub rozszerz, Doubleaby obsłużyć miejsca N-dziesiętne:

      extension Double {    
          func rounded(toDecimalPlaces n: Int) -> Double {
              let multiplier = pow(10, Double(n))
              return (multiplier * self).rounded()/multiplier
          }
      }
staticVoidMan
źródło
6

Jest to bardziej elastyczny algorytm zaokrąglania do N cyfr znaczących

Rozwiązanie Swift 3

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
Nikita Ivaniushchenko
źródło
6

Najlepszym sposobem sformatowania podwójnej właściwości jest użycie predefiniowanych metod Apple.

mutating func round(_ rule: FloatingPointRoundingRule)

FloatingPointRoundingRule to wyliczenie, które ma następujące możliwości

Przypadki wyliczenia:

case awayFromZero Zaokrąglij do najbliższej dozwolonej wartości, której wielkość jest większa lub równa wielkości źródła.

case down Zaokrąglij do najbliższej dozwolonej wartości, która jest mniejsza lub równa źródłu.

case toNearestOrAwayFromZero Round do najbliższej dozwolonej wartości; jeśli dwie wartości są jednakowo bliskie, wybierana jest ta o większej wielkości.

case toNearestOrEven Zaokrąglij do najbliższej dozwolonej wartości; jeśli dwie wartości są jednakowo bliskie, wybierana jest parzysta.

w kierunku Zero Round do najbliższej dozwolonej wartości, której wielkość jest mniejsza lub równa wielkości źródła.

case up Zaokrąglij do najbliższej dozwolonej wartości, która jest większa lub równa źródłu.

var aNumber : Double = 5.2
aNumber.rounded(.up) // 6.0
Abuzar Manzoor
źródło
6

zaokrąglić podwójną wartość do x liczby dziesiętnej
NO. cyfr po przecinku

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
Ayman Badr
źródło
Co się dzieje z tym kodem? Co pokazują trzy przykłady?
przedłużenie
Tylko odpowiedzi na kod nie są pomocne, spróbuj wyjaśnić, co robi każdy z tych przykładów.
Moe
5

Nie szybkie, ale jestem pewien, że masz pomysł.

pow10np = pow(10,num_places);
val = round(val*pow10np) / pow10np;
jog
źródło
4

Wydaje się, że działa to w Swift 5.

Zaskoczony, że nie ma już w tym celu standardowej funkcji.

// Obcięcie miejsc podwójnych do n-dziesiętnych z zaokrągleniem

extension Double {

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

}
Matiu Awaiti
źródło
2

Możesz dodać to rozszerzenie:

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

i nazwij to tak:

let ex: Double = 10.123546789
print(ex.clean) // 10.12
TOUZENE Mohamed Wassim
źródło
Ten jest zgrabną implementacją reprezentowania go jako String. Zastanawiam się, czy jest możliwe lub racjonalne napisanie rozszerzenia liczby reprezentacji cyfr po okresie, który nadal utrzymuje go jako Double.
thinkswift 16.07.19
2

Aby uniknąć niedoskonałości pływaka, użyj opcji Dziesiętny

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

dawny.
1075,58 zaokrągla do 1075,57 przy użyciu pływaka ze skalą: 2 i. Down
1075.58 zaokrągla do 1075,58 przy użyciu dziesiętnego ze skalą: 2 i. Down

Yervand Saribekyan
źródło
1

Zastanawiam się, czy można poprawić dane wejściowe użytkownika. To znaczy, jeśli wprowadzą trzy miejsca po przecinku zamiast dwóch dla kwoty w dolarach. Powiedz 1.111 zamiast 1.11 czy możesz to naprawić zaokrąglając? Odpowiedź z wielu powodów brzmi „nie”! Przy pieniądzach przekraczających np. 0,001 ostatecznie spowoduje problemy w prawdziwym książeczce czekowej.

Oto funkcja służąca do sprawdzania, czy użytkownicy wprowadzają zbyt wiele wartości po okresie. Ale które pozwolą 1., 1.1 i 1.11.

Zakłada się, że wartość została już sprawdzona pod kątem pomyślnej konwersji z ciągu na podwójne.

//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


}
Góral
źródło
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"
Davender Verma
źródło
1
extension String{
  var roundedValue:String {
     return String(format: "%.3f", self)
}}

Stosowanie :

totalWorkTimeInHours.roundedValue
Bhargav Sejpal
źródło
1

Oto jeden dla SwiftUI, jeśli potrzebujesz elementu Text o wartości liczbowej.

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

    var body : some View {
        Text(String(format: "%.\(digits)f", number))
    }
}
FrankByte.com
źródło