web-dev-qa-db-fra.com

Arrondir une CGFloat dans Swift

Comment puis-je rassembler un CGFloat à Swift? J'ai essayé ceil(CDouble(myCGFloat)) mais cela ne fonctionne que sur iPad Air et iPhone 5S.

Lorsque j'exécute sur un autre appareil simulé, une erreur s'affiche en indiquant 'NSNumber' is not a subtype of 'CGFloat'

71
Oskar Persson

Mise à jour : Apple ont maintenant défini certaines versions spécifiques à CGFloat de fonctions communes telles que ceil:

func ceil(x: CGFloat) -> CGFloat

... spécifiquement pour faire face à la différence 32/64 bits. Si vous utilisez simplement ceil avec un argument CGFloat, il devrait maintenant fonctionner sur toutes les architectures.

Ma réponse originale:

C'est assez horrible, je pense, mais quelqu'un peut-il penser à un meilleur moyen? #if ne semble pas fonctionner pour CGFLOAT_IS_DOUBLE; Je pense que vous êtes limité à la construction de configurations, à partir de quoi je peux voir dans la documentation pour la compilation conditionnelle .

var x = CGFloat(0.5)

#if Arch(x86_64) || Arch(arm64)
var test = ceil(x)
#else
var test = ceilf(x)
#endif
109
Matt Gibson

Avec Swift 5, vous pouvez choisir l’un des 3 chemins suivants afin d’arrondir un CGFloat.


#1. Utilisation de la méthode CGFloatrounded(_:)

Le protocole FloatingPoint donne aux types qui s'y conforment une méthode rounded(_:) . CGFloat's rounded(_:) a la déclaration suivante:

func rounded(_ rule: FloatingPointRoundingRule) -> CGFloat

Renvoie cette valeur arrondie à une valeur intégrale à l'aide de la règle d'arrondi spécifiée.

L'exemple de code Playground ci-dessous montre comment utiliser rounded(_:) pour arrondir une valeur CGFloat:

import CoreGraphics

let value1: CGFloat = -0.4
let value2: CGFloat = -0.5
let value3: CGFloat = -1
let value4: CGFloat = 0.4
let value5: CGFloat = 0.5
let value6: CGFloat = 1

let roundedValue1 = value1.rounded(.up)
let roundedValue2 = value2.rounded(.up)
let roundedValue3 = value3.rounded(.up)
let roundedValue4 = value4.rounded(.up)
let roundedValue5 = value5.rounded(.up)
let roundedValue6 = value6.rounded(.up)

print(roundedValue1) // prints -0.0
print(roundedValue2) // prints -0.0
print(roundedValue3) // prints -1.0
print(roundedValue4) // prints 1.0
print(roundedValue5) // prints 1.0
print(roundedValue6) // prints 1.0

# 2. Utiliser ceil(_:) fonction

Darwin fournit une fonction ceil(_:) ayant la déclaration suivante:

func ceil<T>(_ x: T) -> T where T : FloatingPoint

Le code de Playground ci-dessous montre comment utiliser ceil(_:) pour arrondir une valeur CGFloat:

import CoreGraphics

let value1: CGFloat = -0.4
let value2: CGFloat = -0.5
let value3: CGFloat = -1
let value4: CGFloat = 0.4
let value5: CGFloat = 0.5
let value6: CGFloat = 1

let roundedValue1 = ceil(value1)
let roundedValue2 = ceil(value2)
let roundedValue3 = ceil(value3)
let roundedValue4 = ceil(value4)
let roundedValue5 = ceil(value5)
let roundedValue6 = ceil(value6)

print(roundedValue1) // prints -0.0
print(roundedValue2) // prints -0.0
print(roundedValue3) // prints -1.0
print(roundedValue4) // prints 1.0
print(roundedValue5) // prints 1.0
print(roundedValue6) // prints 1.0

# 3. Utiliser NumberFormatter

Si vous voulez arrondir un CGFloat et le formater avec style dans la même opération, vous pouvez utiliser NumberFormatter .

import Foundation
import CoreGraphics

let value1: CGFloat = -0.4
let value2: CGFloat = -0.5
let value3: CGFloat = -1
let value4: CGFloat = 0.4
let value5: CGFloat = 0.5
let value6: CGFloat = 1

let formatter = NumberFormatter()
formatter.numberStyle = NumberFormatter.Style.decimal
formatter.roundingMode = NumberFormatter.RoundingMode.ceiling
formatter.maximumFractionDigits = 0

let roundedValue1 = formatter.string(for: value1)
let roundedValue2 = formatter.string(for: value2)
let roundedValue3 = formatter.string(for: value3)
let roundedValue4 = formatter.string(for: value4)
let roundedValue5 = formatter.string(for: value5)
let roundedValue6 = formatter.string(for: value6)

print(String(describing: roundedValue1)) // prints Optional("-0")
print(String(describing: roundedValue2)) // prints Optional("-0")
print(String(describing: roundedValue3)) // prints Optional("-1")
print(String(describing: roundedValue4)) // prints Optional("1")
print(String(describing: roundedValue5)) // prints Optional("1")
print(String(describing: roundedValue6)) // prints Optional("1")
28
Imanou Petit

La syntaxe la plus correcte serait probablement:

var f: CGFloat = 2.5
var roundedF = CGFloat(ceil(Double(f)))

Pour utiliser ceil je vais d’abord faire le CGFloat un Double et après plafond, je le reconvertis en CGFloat.

Cela fonctionne lorsque CGFloat est défini comme CFloat ou CDouble.

Vous pouvez également définir un ceil pour les floats (Ceci a été réellement implémenté dans Swift 2):

func ceil(f: CFloat) -> CFloat {
   return ceilf(f)
}

Ensuite, vous pourrez appeler directement

var roundedF: CGFloat = ceil(f)

tout en préservant la sécurité de type.

Je pense en fait que cela devrait être la solution choisie par Apple, au lieu d’avoir des fonctions séparées ceil et ceilf car elles n’ont aucun sens dans Swift.

20
Sulthan

à partir de Swift Standard Library , vous pouvez également le contourner sur place:

var value: CGFloat = -5.7
value.round(.up) // -5.0
7
holex

Construire à partir de la réponse de holex. J'ai fait

func accurateRound(value: Double) -> Int {

            var d : Double = value - Double(Int(value))

            if d < 0.5 {
                return Int(value)
            } else {
                return Int(value) + 1
            }
        }

- éditer l'extension d'édition -

J'ai aussi récemment transformé cela en une extension pour Floats que je partagerais aussi :)

extension Float {
    func roundToInt() -> Int{
        var value = Int(self)
        var f = self - Float(value)
        if f < 0.5{
            return value
        } else {
            return value + 1
        }
    }
}

Cela fait en sorte que vous pouvez juste être comme

var f : Float = 3.3
f.roundToInt()
5
Krtko

Utilisez-le sur Swift 5

let x = 6.5

// Equivalent to the C 'round' function:
print(x.rounded(.toNearestOrAwayFromZero))
// Prints "7.0"

// Equivalent to the C 'trunc' function:
print(x.rounded(.towardZero))
// Prints "6.0"

// Equivalent to the C 'ceil' function:
print(x.rounded(.up))
// Prints "7.0"

// Equivalent to the C 'floor' function:
print(x.rounded(.down))
// Prints "6.0"
0
mohsen