Swift 3 & 4 - facendo uso del rounded(_:)
metodo come indicato nel FloatingPoint
protocollo
Il FloatingPoint
protocollo (al quale ad esempio Double
e Float
conforme) progetta il rounded(_:)
metodo
func rounded(_ rule: FloatingPointRoundingRule) -> Self
Dov'è FloatingPointRoundingRule
un'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
, ceil
o 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 floor
funzione 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 round
funzione 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 trunc
funzione 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 Int
da FloatPoint
inizializzazione dopo l'arrotondamento), potremmo semplicemente fare uso del fatto che quando si inizializza un Int
utilizza 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 ceil
funzione 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 FloatingPoint
verificare l'equivalenza delle funzioni C alle diverse FloatingPointRoundingRule
regole
Se vorremmo, possiamo dare un'occhiata al codice sorgente del FloatingPoint
protocollo per vedere direttamente la funzione C equivalente alle FloatingPointRoundingRule
regole 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