Swift 3 y 4: haciendo uso del rounded(_:)
método como se muestra en el FloatingPoint
protocolo
El FloatingPoint
protocolo (al cual, por ejemplo, Double
y se Float
ajusta) esboza el rounded(_:)
método
func rounded(_ rule: FloatingPointRoundingRule) -> Self
¿Dónde FloatingPointRoundingRule
hay una enumeración que enumera una serie de reglas de redondeo diferentes:
case awayFromZero
Redondee al valor permitido más cercano cuya magnitud sea mayor o igual que la de la fuente.
case down
Redondea al valor permitido más cercano que sea menor o igual que la fuente.
case toNearestOrAwayFromZero
Redondear al valor permitido más cercano; Si dos valores son igualmente cercanos, se elige el de mayor magnitud.
case toNearestOrEven
Redondear al valor permitido más cercano; Si dos valores son igualmente cercanos, se elige el par.
case towardZero
Redondee al valor permitido más cercano cuya magnitud sea menor o igual que la de la fuente.
case up
Redondea al valor permitido más cercano que sea mayor o igual que la fuente.
Utilizamos ejemplos similares a los de la excelente respuesta de @ Suragch para mostrar estas diferentes opciones de redondeo en la práctica.
.awayFromZero
Redondee al valor permitido más cercano cuya magnitud sea mayor o igual que la de la fuente; no hay equivalente directo entre las funciones de C, ya que esto utiliza, condicionalmente en el signo de self
, ceil
o floor
, para valores positivos y negativos de self
, respectivamente.
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 a la floor
función 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 a la round
función 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
También se puede acceder a esta regla de redondeo utilizando el rounded()
método de argumento cero .
3.000.rounded() // 3.0
// ...
(-3.000).rounded() // -3.0
// ...
.toNearestOrEven
Redondear al valor permitido más cercano; si dos valores son igualmente cercanos, se elige el par; equivalente a la función C rint
(/ muy similar 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 a la trunc
función 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
Si el propósito del redondeo es prepararse para trabajar con un número entero (por ejemplo, usando Int
por FloatPoint
inicialización después del redondeo), podríamos simplemente hacer uso del hecho de que al inicializar un Int
uso de a Double
(o Float
etc.), la parte decimal se truncará.
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 a la ceil
función 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
Anexo: visitando el código fuente para FloatingPoint
verificar la equivalencia de las funciones C con los diferentesFloatingPointRoundingRule
reglas
Si quisiéramos, podemos echar un vistazo al código fuente del FloatingPoint
protocolo para ver directamente los equivalentes de la función C al públicoFloatingPointRoundingRule
reglas .
Desde swift / stdlib / public / core / FloatingPoint.swift.gyb , vemos que la implementación predeterminada del rounded(_:)
método nos convierte en el round(_:)
método de mutación :
public func rounded(_ rule: FloatingPointRoundingRule) -> Self {
var lhs = self
lhs.round(rule)
return lhs
}
En swift / stdlib / public / core / FloatingPointTypes.swift.gyb encontramos la implementación predeterminada de round(_:)
, en la que la equivalencia entre las FloatingPointRoundingRule
reglas y las funciones de redondeo en C es evidente:
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()
desafortunadamente no está disponible en un patio de juegos