Arrondir une valeur double à x nombre de décimales dans swift

Quelqu'un peut-il me dire comment arrondir une double valeur à x nombre de décimales dans Swift?

J'ai:

var totalWorkTimeInHours = (totalWorkTime/60/60)

Avec {[1] } étant un NSTimeInterval (double) en second.

totalWorkTimeInHours me donnera les heures, mais il me donne la quantité de temps dans un nombre aussi long précis, par exemple 1.543240952039......

Comment arrondir ceci à, disons, 1.543 quand j'imprime totalWorkTimeInHours?

268
demandé sur Tot Zam 2014-12-07 04:27:21

21 réponses

Vous pouvez utiliser la fonction round de Swift pour y parvenir.

Pour arrondir un Double avec une précision de 3 chiffres, multipliez-le d'abord par 1000, arrondissez-le et divisez le résultat arrondi par 1000:

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

Autre que tout type de solutions printf(...) ou String(format: ...), le résultat de cette opération est toujours de type Double.

Modifier:
En ce qui concerne les commentaires que cela ne fonctionne parfois pas, veuillez lire ceci:

Ce Que Tout Informaticien Devrait Savoir Arithmétique À Virgule Flottante

269
répondu zisoft 2017-02-28 18:34:26

Extension pour Swift 2

Une solution plus générale est l'extension suivante, qui fonctionne avec Swift 2 et 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
    }
}


Extension pour Swift 3

Dans Swift 3 round est remplacé par 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
    }
}


Exemple qui renvoie double arrondi à 4 décimales:

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
répondu Sebastian 2017-08-16 05:18:43

Utilisez le constructeur String qui prend une chaîne format:

print(String(format: "%.3f", totalWorkTimeInHours))
213
répondu vacawama 2015-12-01 16:43:30

Avec Swift 4, en fonction de vos besoins, vous pouvez choisir l'un des 9 styles suivants, afin d'avoir un résultat arrondi à partir d'un Double.


#1. À l'aide de FloatingPoint rounded() méthode

Dans le cas le plus simple, vous pouvez utiliser Double round() méthode.

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. À l'aide de FloatingPoint rounded(_:) méthode

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. Utilisation de la fonction Darwin round

Fondation offre une fonction round via 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. Utilisation d'une méthode personnalisée d'extension Double construite avec les fonctions Darwin round et pow

Si vous voulez répéter l'opération précédente plusieurs fois, refactoriser votre code peut être une bonne idée.

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. À l'aide de NSDecimalNumber rounding(accordingToBehavior:) méthode

Si nécessaire, NSDecimalNumber offre une solution verbeuse mais puissante pour arrondir les nombres décimaux.

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. À l'aide de NSDecimalRound(_:_:_:_:) fonction

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. À l'aide de NSString init(format:arguments:) initialiseur

Si vous voulez renvoyer un NSString de votre opération d'arrondi, l'utilisation de l'initialiseur NSString est une solution simple mais efficace.

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. À l'aide de String init(format:_:) initialiseur

Le type String de Swift est relié à la classe NSString de Foundation (vous pouvez en apprendre plus à ce sujet en lisant le langage de programmation Swift). Par conséquent, vous pouvez utiliser le code suivant dans pour renvoyer un String de votre opération d'arrondi:

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. À l'aide de NumberFormatter

Si vous prévoyez d'obtenir un String? de votre opération d'arrondi, NumberFormatter offre une solution hautement personnalisable.

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
répondu Imanou Petit 2018-02-16 01:07:08

Dans Swift 2.0 et Xcode 7.2:

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

Exemple:

entrez la description de l'image ici

79
répondu Claudio Guirunas 2016-12-20 10:32:40

En S'appuyant sur la réponse de Yogi, voici une fonction Swift qui fait le travail:

func roundToPlaces(value:Double, places:Int) -> Double {
    let divisor = pow(10.0, Double(places))
    return round(value * divisor) / divisor
}
24
répondu Ash 2015-02-04 11:22:19

C'est un code entièrement travaillé

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)

Sortie-123

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

Sortie - 123.3

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

Sortie - 123.33

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

Sortie-123.326

16
répondu Krunal Patel 2018-01-27 10:45:20

Dans Swift 3.0 et Xcode 8.0:

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

Utilisez cette extension comme ceci,

let doubleValue = 3.567
let roundedValue = doubleValue.roundTo(places: 2)
print(roundedValue) // prints 3.56
13
répondu jaiswal Rajan 2016-12-19 05:00:06

Le code pour les chiffres spécifiques après les décimales est:

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

Voici le %.3f indique au swift de faire arrondir ce nombre à 3 décimales.et si vous voulez doubler le nombre, vous pouvez utiliser ce code:

/ / Chaîne Pour Doubler

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

13
répondu Ramazan Karami 2018-04-04 06:30:24

Une façon pratique peut être l'utilisation de extension de type Double

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

Utilisation:

let regularPie:  Double = 3.14159
var smallerPie:  Double = regularPie.roundTo3f  // results 3.142
var smallestPie: Double = regularPie.roundTo2f  // results 3.14
8
répondu Marco Leong 2015-09-11 12:56:43

Utilisez la bibliothèque Darwin de fondation intégrée

SWIFT 3

extension Double {

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

}

Utilisation:

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

Sorties: 12.988

7
répondu George Filippakos 2017-04-30 23:41:21

C'est une sorte de solution de contournement longue, qui peut être utile si vos besoins sont un peu plus complexes. Vous pouvez utiliser un formateur de nombres dans Swift.

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

Supposons que votre variable que vous voulez imprimer soit

var printVar = 3.567

Cela permettra de s'assurer qu'il est retourné dans le format souhaité:

numberFormatter.StringFromNumber(printVar)

Le résultat ici sera donc " 3.6 " (arrondi). Bien que ce ne soit pas la solution la plus économique, je le donne parce que L'OP a mentionné l'impression (auquel cas une chaîne n'est pas indésirable), et parce que cette classe permet de définir plusieurs paramètres.

6
répondu Inkidu616 2016-03-14 22:08:59

Je voudrais utiliser

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

Et changer .3f à n'importe quel nombre de nombres décimaux dont vous avez besoin

6
répondu Mohsen Hossein pour 2016-10-27 12:24:59

Pas rapide mais je suis sûr que vous avez l'idée.

pow10np = pow(10,num_places);
val = round(val*pow10np) / pow10np;
4
répondu yogi 2015-01-08 00:12:22

C'est un algorithme plus flexible d'arrondi à n chiffres significatifs

Solution 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
4
répondu Nikita Ivaniushchenko 2017-02-07 19:44:13

Arrondir une valeur double à X nombre de décimales
AUCUN. de chiffres après décimal

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
répondu Ayman Badr 2017-12-21 11:53:24

La meilleure façon de formater une propriété double est d'utiliser les méthodes prédéfinies Apple.

mutating func round(_ rule: FloatingPointRoundingRule)

FloatingPointRoundingRule est une énumération qui a les possibilités suivantes

Cas D'Énumération:

Cas awayFromZero Arrondir à la valeur autorisée la plus proche dont la magnitude est supérieure ou égale à celle de la source.

Cas vers le bas Tour à la plus proche valeur autorisée est inférieure ou égale à la source.

Affaire toNearestOrAwayFromZero Arrondir à la valeur autorisée la plus proche; si deux valeurs sont également proches, celle avec la plus grande magnitude est choisie.

Cas toNearestOrEven Arrondir à la valeur autorisée la plus proche; si deux valeurs sont également proches, la valeur paire est choisie.

Cas verszero Tour à la plus proche valeur autorisée dont la magnitude est inférieure ou égale à celle de la source.

Cas vers le haut Arrondir à la valeur autorisée la plus proche qui est supérieure à ou égal à la source.

var aNumber : Double = 5.2
aNumber.rounded(.up) // 6.0
3
répondu Abuzar Manzoor 2017-06-05 14:22:55

Soit:

  1. En utilisant String(format:):

    • Transtypage Double à String avec %.3f spécificateur de format et ensuite de retour à Double

      Double(String(format: "%.3f", 10.123546789))!
      
    • Ou étendre Double pour gérer N décimales:

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

    • Multiplier par 10^3, arrondir puis diviser par 10^3...

      (1000 * 10.123546789).rounded()/1000
      
    • Ou étendre Double pour gérer N-décimal lieux:

      extension Double {    
          func rounded(toDecimalPlaces n: Int) -> Double {
              let multiplier = pow(10, Double(n))
              return (multiplier * self).rounded()/multiplier
          }
      }
      
3
répondu staticVoidMan 2018-08-20 09:39:01

Si vous voulez arrondir les valeurs Double, vous pouvez utiliser Swift Decimal afin de ne pas introduire d'erreurs qui peuvent apparaître lorsque vous essayez de calculer avec ces valeurs arrondies. Si vous utilisez Decimal, il peut représenter avec précision les valeurs décimales de cette valeur à virgule flottante arrondie.

Donc vous pouvez faire:

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

Ensuite, vous pouvez obtenir la valeur Decimal arrondie comme suit:

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

Et si vous voulez l'afficher avec un nombre spécifié de décimales (ainsi que localiser la chaîne pour le paramètres régionaux actuels de l'utilisateur), vous pouvez utiliser un NumberFormatter:

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

if let string = formatter.string(for: value) {
    print(string)
}
1
répondu Rob 2018-02-05 07:36:38

J'ai trouvé cela se demandant s'il est possible de corriger l'entrée d'un utilisateur. C'est-à-dire s'ils entrent trois décimales au lieu de deux pour un montant en dollars. Dites 1.111 au lieu de 1.11 pouvez-vous le réparer en arrondissant? La réponse pour de nombreuses raisons est non! Avec de l'argent, quelque chose de plus, c'est-à-dire 0.001 finirait par causer des problèmes dans un vrai chéquier.

Voici une fonction pour vérifier l'entrée des utilisateurs pour trop de valeurs après la période. Mais qui permettra 1., 1.1 et 1.11.

On suppose que le la valeur a déjà été vérifiée pour la conversion réussie d'une chaîne en Double.

//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
répondu Mountain Man 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
répondu Davender Verma Soni 2018-07-28 09:45:52