web-dev-qa-db-fra.com

Comment arrondir un Double à l'Int le plus proche dans swift?

J'essaie de faire un calculateur de taux de croissance (Double) qui arrondira le résultat à l'entier le plus proche et le recalculera à partir de là, en tant que tel:

let firstUsers = 10.0
let growth = 0.1
var users = firstUsers
var week = 0


while users < 14 {
    println("week \(week) has \(users) users")
    users += users * growth
    week += 1
}

mais j'ai été incapable jusqu'à présent.

EDIT Je l'ai fait comme ça:

var firstUsers = 10.0
let growth = 0.1
var users:Int = Int(firstUsers)
var week = 0


while users <= 14 {
    println("week \(week) has \(users) users")
    firstUsers += firstUsers * growth
    users = Int(firstUsers)
    week += 1
}

Bien que cela ne me dérange pas que les chiffres soient toujours arrondis, je ne l’aime pas parce que firstUsers devait devenir une variable et changer tout au long du programme (afin de faire le calcul suivant), ce que je n’aime pas. veux que cela se produise.

145
duarte harris

Il y a une round disponible dans la bibliothèque Foundation (c'est en fait dans Darwin, mais Foundation importe Darwin et la plupart du temps, vous voudrez utiliser Foundation au lieu d’utiliser Darwin directement) .

import Foundation

users = round(users)

Lancer votre code dans une cour de récréation et appeler ensuite:

print(round(users))

Les sorties:

15.0

round() toujours arrondi lorsque la décimale est >= .5 et décroissant lorsque < .5 (arrondi standard). Vous pouvez utiliser floor() pour forcer les arrondis, et ceil() pour les arrondir.

Si vous devez arrondir à un endroit spécifique, multipliez-le par pow(10.0, number of places), round, puis divisez-le par pow(10, number of places):

Arrondir à 2 décimales:

let numberOfPlaces = 2.0
let multiplier = pow(10.0, numberOfPlaces)
let num = 10.12345
let rounded = round(num * multiplier) / multiplier
print(rounded)

Les sorties:

10.12

Remarque: En raison du fonctionnement des calculs à virgule flottante, rounded risque de ne pas toujours être parfaitement précis. Mieux vaut penser à une approximation de l'arrondi. Si vous faites cela à des fins d’affichage, il est préférable d’utiliser le format de chaîne pour formater le nombre plutôt que d’utiliser des maths pour l’arrondir.

218
Mike S

Pour arrondir un double au nombre entier le plus proche, utilisez simplement round() .

var x = 3.7
x.round() // x = 4.0

Si vous ne souhaitez pas modifier la valeur d'origine, utilisez rounded() :

let x = 3.7
let y = x.rounded() // y = 4.0. x = 3.7

Comme on pouvait s'y attendre ( ou non ), un nombre tel que 3.5 est arrondi et un nombre tel que -3.5 est arrondi. Si vous avez besoin d'un comportement d'arrondi différent, vous pouvez utiliser l'une des règles d'arrondi . Par exemple:

var x = 3.7
x.round(.towardZero) // 3.0

Si vous avez besoin d'un Int réel, il vous suffit de le convertir en un (mais uniquement si vous êtes certain que le double ne sera pas supérieur à Int.max):

let myInt = Int(myDouble.rounded())

Remarques

  • Cette réponse est complètement réécrite. Mon ancienne réponse concernait les fonctions mathématiques du C telles que round, lround, floor et ceil. Cependant, maintenant que Swift a cette fonctionnalité intégrée, je ne peux plus recommander l'utilisation de ces fonctions. Merci à @dfri de me l'avoir signalé. Découvrez l'excellente réponse de @ dfri ici . J'ai aussi fait quelque chose de similaire pour arrondir un CGFloat .
127
Suragch

Swift 3 & 4 - utilisation de la méthode rounded(_:) telle que définie dans le protocole FloatingPoint

Le protocole FloatingPoint (auquel, par exemple, Double et Float se conforme) bleuit la _ MÉTHODE rounded(_:)

_func rounded(_ rule: FloatingPointRoundingRule) -> Self
_

FloatingPointRoundingRule est une énumération énumérant un certain nombre de règles d'arrondissement différentes:

case awayFromZero

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

case down

Arrondissez à la valeur autorisée la plus proche qui est inférieure ou égale à la source.

case toNearestOrAwayFromZero

Arrondir à la valeur autorisée la plus proche. si deux valeurs sont également proches, on choisit celle de plus grande magnitude.

case toNearestOrEven

Arrondir à la valeur autorisée la plus proche. si deux valeurs sont également proches, le même est choisi.

case towardZero

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

case up

Arrondissez à la valeur autorisée la plus proche, supérieure ou égale à la source.

Nous utilisons des exemples similaires à ceux de excellente réponse de @ Suragch pour montrer ces différentes options d'arrondi dans la pratique.

_.awayFromZero_

Arrondir à la valeur autorisée la plus proche dont la magnitude est supérieure ou égale à celle de la source; pas d'équivalent direct parmi les fonctions C, car cela utilise, conditionnellement sur le signe de self, ceil ou floor, pour les valeurs positives et négatives de self, respectivement.

_3.000.rounded(.awayFromZero) // 3.0
3.001.rounded(.awayFromZero) // 4.0
3.999.rounded(.awayFromZero) // 4.0

(-3.000).rounded(.awayFromZero) // -3.0
(-3.001).rounded(.awayFromZero) // -4.0
(-3.999).rounded(.awayFromZero) // -4.0
_

_.down_

Équivalent à la fonction C floor.

_3.000.rounded(.down) // 3.0
3.001.rounded(.down) // 3.0
3.999.rounded(.down) // 3.0

(-3.000).rounded(.down) // -3.0
(-3.001).rounded(.down) // -4.0
(-3.999).rounded(.down) // -4.0
_

_.toNearestOrAwayFromZero_

Équivalent à la fonction C round.

_3.000.rounded(.toNearestOrAwayFromZero) // 3.0
3.001.rounded(.toNearestOrAwayFromZero) // 3.0
3.499.rounded(.toNearestOrAwayFromZero) // 3.0
3.500.rounded(.toNearestOrAwayFromZero) // 4.0
3.999.rounded(.toNearestOrAwayFromZero) // 4.0

(-3.000).rounded(.toNearestOrAwayFromZero) // -3.0
(-3.001).rounded(.toNearestOrAwayFromZero) // -3.0
(-3.499).rounded(.toNearestOrAwayFromZero) // -3.0
(-3.500).rounded(.toNearestOrAwayFromZero) // -4.0
(-3.999).rounded(.toNearestOrAwayFromZero) // -4.0
_

On peut également accéder à cette règle d’arrondi en utilisant l’argument zéro méthode rounded() .

_3.000.rounded() // 3.0
// ...

(-3.000).rounded() // -3.0
// ...
_

_.toNearestOrEven_

Arrondir à la valeur autorisée la plus proche. si deux valeurs sont également proches, le même est choisi; équivalent à la fonction C rint (/ très similaire à nearbyint).

_3.499.rounded(.toNearestOrEven) // 3.0
3.500.rounded(.toNearestOrEven) // 4.0 (up to even)
3.501.rounded(.toNearestOrEven) // 4.0

4.499.rounded(.toNearestOrEven) // 4.0
4.500.rounded(.toNearestOrEven) // 4.0 (down to even)
4.501.rounded(.toNearestOrEven) // 4.0
_

_.towardZero_

Équivalent à la fonction C trunc.

_3.000.rounded(.towardZero) // 3.0
3.001.rounded(.towardZero) // 3.0
3.999.rounded(.towardZero) // 3.0

(-3.000).rounded(.towardZero) // 3.0
(-3.001).rounded(.towardZero) // 3.0
(-3.999).rounded(.towardZero) // 3.0
_

Si le but de l'arrondi est de préparer le travail avec un entier (par exemple, en utilisant l'initialisation Int par FloatPoint après l'arrondi), nous pourrions simplement utiliser le fait que lors de l'initialisation d'un Int en utilisant un Double (ou Float etc.), la partie décimale sera tronqué.

_Int(3.000) // 3
Int(3.001) // 3
Int(3.999) // 3

Int(-3.000) // -3
Int(-3.001) // -3
Int(-3.999) // -3
_

_.up_

Équivalent à la fonction C ceil.

_3.000.rounded(.up) // 3.0
3.001.rounded(.up) // 4.0
3.999.rounded(.up) // 4.0

(-3.000).rounded(.up) // 3.0
(-3.001).rounded(.up) // 3.0
(-3.999).rounded(.up) // 3.0
_

Addendum: visite du code source de FloatingPoint pour vérifier l’équivalence des fonctions C avec les différentes règles FloatingPointRoundingRule

Si nous le souhaitons, examinons le code source du protocole FloatingPoint pour voir directement les équivalents de la fonction C aux règles publiques FloatingPointRoundingRule.

De Swift/stdlib/public/core/FloatingPoint.Swift.gyb , nous voyons que l'implémentation par défaut de la méthode rounded(_:) nous amène à la méthode mutante round(_:):

_public func rounded(_ rule: FloatingPointRoundingRule) -> Self {
    var lhs = self
    lhs.round(rule)
    return lhs
}
_

De Swift/stdlib/public/core/FloatingPointTypes.Swift.gyb , nous trouvons l'implémentation par défaut de round(_:), dans laquelle l'équivalence entre les règles FloatingPointRoundingRule et les fonctions d'arrondi C est apparente:

_public mutating func round(_ rule: FloatingPointRoundingRule) {
    switch rule {
    case .toNearestOrAwayFromZero:
        _value = Builtin.int_round_FPIEEE${bits}(_value)
    case .toNearestOrEven:
        _value = Builtin.int_rint_FPIEEE${bits}(_value)
    case .towardZero:
        _value = Builtin.int_trunc_FPIEEE${bits}(_value)
    case .awayFromZero:
        if sign == .minus {
            _value = Builtin.int_floor_FPIEEE${bits}(_value)
        }
        else {
            _value = Builtin.int_ceil_FPIEEE${bits}(_value)
        }
    case .up:
        _value = Builtin.int_ceil_FPIEEE${bits}(_value)
    case .down:
        _value = Builtin.int_floor_FPIEEE${bits}(_value)
    }
}
_
66
dfri

Swift 3: Si vous souhaitez arrondir à un certain nombre de chiffres, par exemple. 5.678434 -> 5.68 vous pouvez simplement combiner la fonction round () ou roundf () avec une multiplication:

    let value:Float = 5.678434
    let roundedValue = roundf(value * 100) / 100
    print(roundedValue) //5.68
5
Thoms
**In Swift**

var a = 14.123456789
var b = 14.123456789
var c = 14.123456789
var d = 14.123456789
var e = 14.123456789
var f = 14.123456789

a.rounded(.up)                      //15
b.rounded(.down)                    //14
c.rounded(.awayFromZero)            //15
d.rounded(.towardZero)              //14
e.rounded(.toNearestOrAwayFromZero) //14
f.rounded(.toNearestOrEven)         //14
3
Sai kumar Reddy

Vous pouvez également étendre FloatingPoint dans Swift 3 comme suit:

extension FloatingPoint {
    func rounded(to n: Int) -> Self {
        let n = Self(n)
        return (self / n).rounded() * n

    }
}

324.0.rounded(to: 5)   // 325
2
Leo Dabus

Swift 3

var myNum = 8.09

myNum.rounded () // resultat = 8 qui est stocké dans myNum

1
Dattatray Deokar