Swift 3 & 4 - facendo uso del rounded(_:)metodo come indicato nel FloatingPointprotocollo
Il FloatingPointprotocollo (al quale ad esempio Doublee Floatconforme) progetta il rounded(_:)metodo
func rounded(_ rule: FloatingPointRoundingRule) -> Self
Dov'è FloatingPointRoundingRuleun'enum che elenca un numero di diverse regole di arrotondamento:
case awayFromZero
Arrotonda al valore consentito più vicino la cui grandezza è maggiore o uguale a quella della sorgente.
case down
Arrotondare al valore consentito più vicino che è minore o uguale alla fonte.
case toNearestOrAwayFromZero
Arrotondare al valore consentito più vicino; se due valori sono ugualmente vicini, viene scelto quello con maggiore magnitudine.
case toNearestOrEven
Arrotondare al valore consentito più vicino; se due valori sono ugualmente vicini, viene scelto quello pari.
case towardZero
Arrotonda al valore consentito più vicino la cui grandezza è inferiore o uguale a quella della sorgente.
case up
Arrotondare al valore consentito più vicino maggiore o uguale alla fonte.
Facciamo uso di esempi simili a quelli dell'eccellente risposta di @ Suragch per mostrare in pratica queste diverse opzioni di arrotondamento.
.awayFromZero
Arrotonda al valore consentito più vicino la cui grandezza è maggiore o uguale a quella della sorgente; non diretta equivalente tra le funzioni C, in quanto questo tipo di uso, condizionatamente segno self, ceilo floor, per valori positivi e negativi di self, rispettivamente.
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
Equivalente alla floorfunzione C.
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
Equivalente alla roundfunzione C.
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
È possibile accedere a questa regola di arrotondamento anche utilizzando il rounded()metodo argomento zero .
3.000.rounded() // 3.0
// ...
(-3.000).rounded() // -3.0
// ...
.toNearestOrEven
Arrotondare al valore consentito più vicino; se due valori sono ugualmente vicini, viene scelto anche quello; equivalente alla funzione C rint(/ molto simile a 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) // 5.0 (up to nearest)
.towardZero
Equivalente alla truncfunzione C.
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
Se lo scopo dell'arrotondamento è quello di preparare a lavorare con un intero (ad esempio utilizzando Intda FloatPointinizializzazione dopo l'arrotondamento), potremmo semplicemente fare uso del fatto che quando si inizializza un Intutilizza una Double(o Float, ecc), la parte decimale verrà troncata via.
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
Equivalente alla ceilfunzione C.
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: visita del codice sorgente per FloatingPointverificare l'equivalenza delle funzioni C alle diverse FloatingPointRoundingRuleregole
Se vorremmo, possiamo dare un'occhiata al codice sorgente del FloatingPointprotocollo per vedere direttamente la funzione C equivalente alle FloatingPointRoundingRuleregole pubbliche .
Da swift / stdlib / public / core / FloatingPoint.swift.gyb vediamo che l'implementazione predefinita del rounded(_:)metodo ci rende il round(_:)metodo mutante :
public func rounded(_ rule: FloatingPointRoundingRule) -> Self {
var lhs = self
lhs.round(rule)
return lhs
}
Da swift / stdlib / public / core / FloatingPointTypes.swift.gyb troviamo l'implementazione predefinita di round(_:), in cui FloatingPointRoundingRuleè evidente l'equivalenza tra le regole e le funzioni di arrotondamento C:
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)
}
}
pow()purtroppo non disponibile in un parco giochi