Zaokrąglanie podwójnej wartości do x liczby miejsc po przecinku w języku swift

Czy ktoś może mi powiedzieć, jak zaokrąglić podwójną wartość do X liczby miejsc po przecinku w Swift?

Mam:

var totalWorkTimeInHours = (totalWorkTime/60/60)

Z totalWorkTime jako NSTimeInterval (double) w sekundzie.

totalWorkTimeInHours da mi godziny, ale daje mi ilość czasu w tak długiej dokładnej liczbie np. 1.543240952039......

Jak zaokrąglić to do, powiedzmy, 1.543 przy drukowaniu totalWorkTimeInHours?

Author: Tot Zam, 2014-12-07

21 answers

Możesz użyć funkcji Swift round, aby to osiągnąć.

Aby zaokrąglić a Double z dokładnością do 3 cyfr, najpierw pomnóż ją przez 1000, zaokrągl i podziel wynik zaokrąglenia 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: ...), wynik tej operacji jest nadal typu Double.

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

O Czym Powinien Wiedzieć Każdy Informatyk Arytmetyka Zmiennoprzecinkowa

 269
Author: zisoft,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-28 18:34:26

Rozszerzenie dla Swift 2

[7]} 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 dla Swift 3

W języku Swift 3 round zastępuje się przez 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 zwracający Podwójne zaokrąglenie 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
 358
Author: Sebastian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-16 05:18:43

Użyj konstruktora String, który przyjmuje format string:

print(String(format: "%.3f", totalWorkTimeInHours))
 213
Author: vacawama,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-01 16:43:30

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


#1. Za pomocą FloatingPoint rounded() metoda

W najprostszym przypadku możesz użyć Double round() metoda.

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. Za pomocą FloatingPoint rounded(_:) metoda

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

#3. Korzystanie z funkcji Darwina round

Fundacja oferuje round funkcję poprzez 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. Wykorzystanie niestandardowej metody rozszerzenia Double zbudowanej z funkcji Darwin round i pow

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

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. Za pomocą NSDecimalNumber rounding(accordingToBehavior:) metoda

W razie potrzeby, NSDecimalNumber oferuje obszerne, 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. Za pomocą NSDecimalRound(_:_:_:_:) function

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. Za pomocą NSString init(format:arguments:) initializer

Jeśli chcesz zwrócić NSString z operacji zaokrąglania, użycie inicjalizatora NSString 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. Za pomocą String init(format:_:) initializer

Typ Swift String jest łączony z klasą Foundation NSString (możesz dowiedzieć się więcej o tym czytając język programowania Swift ). Dlatego możesz użyć poniższego kodu w aby zwrócić String z operacji 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ę uzyskać String? z operacji zaokrąglania, NumberFormatter oferuje 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")
 130
Author: Imanou Petit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-16 01:07:08

W Swift 2.0 i Xcode 7.2:

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

Przykład:

Tutaj wpisz opis obrazka

 79
Author: Claudio Guirunas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-20 10:32:40

Na podstawie odpowiedzi Yogi ' ego, oto funkcja Swift, która wykonuje zadanie:

func roundToPlaces(value:Double, places:Int) -> Double {
    let divisor = pow(10.0, Double(places))
    return round(value * divisor) / divisor
}
 24
Author: Ash,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-04 11:22:19

Jest to w pełni działający kod

Swift 3.0 / 4.0, Xcode 9.0 GM / 9.2

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

Wyjście-123

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

Wyjście-123.3

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

Wyjście-123.33

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

Wyjście-123.326

 16
Author: Krunal Patel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-27 10:45: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 w ten sposób,

let doubleValue = 3.567
let roundedValue = doubleValue.roundTo(places: 2)
print(roundedValue) // prints 3.56
 13
Author: jaiswal Rajan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-19 05:00:06

Kod dla konkretnych cyfr po dziesiętnych to:

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

Tutaj %.3f nakazuje swift, aby liczba ta 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))

 13
Author: Ramazan Karami,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-04 06:30:24

Poręcznym 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) }
}

Użycie:

let regularPie:  Double = 3.14159
var smallerPie:  Double = regularPie.roundTo3f  // results 3.142
var smallestPie: Double = regularPie.roundTo2f  // results 3.14
 8
Author: Marco Leong,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-11 12:56:43

Użyj wbudowanej biblioteki Darwina

SWIFT 3

extension Double {

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

}

Użycie:

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

Wyjścia: 12.988

 7
Author: George Filippakos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-30 23:41:21

Jest to rodzaj długiego obejścia, które może się przydać, jeśli twoje potrzeby są trochę bardziej złożone. Możesz użyć programu do formatowania liczb w języku Swift.

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

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

var printVar = 3.567

To upewni się, że zostanie zwrócony w żądanym formacie:

numberFormatter.StringFromNumber(printVar)

Wynik będzie więc "3.6" (zaokrąglony). O ile nie jest to najbardziej ekonomiczne rozwiązanie, to podaję je, ponieważ wspomniany druk OP (w takim przypadku ciąg nie jest niepożądany), a ponieważ klasa ta pozwala na ustawienie wielu parametrów.

 6
Author: Inkidu616,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-14 22:08:59

Użyłbym

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

I zmienić .3f do dowolnej liczby cyfr dziesiętnych, które potrzebujesz

 6
Author: Mohsen Hossein pour,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-27 12:24:59

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

pow10np = pow(10,num_places);
val = round(val*pow10np) / pow10np;
 4
Author: yogi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-08 00:12:22

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

Swift 3 solution

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
 4
Author: Nikita Ivaniushchenko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-07 19:44:13

Zaokrąglenie podwójnej wartości do X liczby dziesiętnej
Nie. cyfry 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
 4
Author: Ayman Badr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-21 11:53:24

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

mutating func round(_ rule: FloatingPointRoundingRule)

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

Przypadki Wyliczenia:

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

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

Case toNearestOrAwayFromZero Zaokrąglenie 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ąglenie do najbliższej dozwolonej wartości; jeśli dwie wartości są jednakowo bliskie, wybierana jest parzysta.

Case towardZero Zaokrąglić do najbliższej dozwolonej wartości, której wielkość jest mniejsza lub równa wielkości źródła.

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

var aNumber : Double = 5.2
aNumber.rounded(.up) // 6.0
 3
Author: Abuzar Manzoor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-05 14:22:55

Albo:

  1. Używając String(format:):

    • Wpisz Double do String ze specyfikatorem formatu %.3f, a następnie z powrotem do Double

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

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

    • Pomnóż przez 10^3, zaokrągl i podziel przez 10^3...

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

      extension Double {    
          func rounded(toDecimalPlaces n: Int) -> Double {
              let multiplier = pow(10, Double(n))
              return (multiplier * self).rounded()/multiplier
          }
      }
      
 3
Author: staticVoidMan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-20 09:39:01

Jeśli chcesz zaokrąglać Double wartości, możesz użyć Swift Decimal, aby nie wprowadzać żadnych błędów, które mogą pojawić się podczas prób obliczenia z tymi zaokrąglonymi wartościami. Jeśli użyjesz Decimal, może ona dokładnie reprezentować wartości dziesiętne tej zaokrąglonej wartości zmiennoprzecinkowej.

Więc możesz 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żna uzyskać zaokrągloną wartość Decimal w następujący sposób:

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

I jeśli chcesz wyświetlić go z określoną liczbą miejsc po przecinku (a także zlokalizować łańcuch dla aktualne ustawienia regionalne 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)
}
 1
Author: Rob,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-05 07:36:38

Znalazłem to zastanawiając się, czy jest możliwe, aby poprawić dane wejściowe użytkownika. To jest, jeśli wprowadzą trzy po przecinku zamiast dwóch dla kwoty dolara. Powiedzmy 1.111 zamiast 1.11 Czy można to naprawić przez zaokrąglenie? Odpowiedź z wielu powodów brzmi: nie! Z pieniędzy coś ponad tj. 0.001 W końcu spowodować problemy w prawdziwej książeczce czekowej.

Tutaj znajduje się funkcja sprawdzająca wprowadzanie przez użytkowników zbyt wielu wartości po okresie. Ale co pozwoli 1., 1.1 i 1.11.

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

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


}
 0
Author: Mountain Man,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-06 01:03:59
//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"
 0
Author: Davender Verma Soni,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-28 09:45:52