Swift 3 e 4 - fazendo uso do rounded(_:)
método conforme o modelo do FloatingPoint
protocolo
O FloatingPoint
protocolo (com o qual, por exemplo, Double
e em Float
conformidade) define o rounded(_:)
método
func rounded(_ rule: FloatingPointRoundingRule) -> Self
Onde FloatingPointRoundingRule
é uma enum enumerando várias regras de arredondamento diferentes:
case awayFromZero
Arredonde para o valor mais próximo permitido, cuja magnitude é maior ou igual à da fonte.
case down
Arredonde para o valor permitido mais próximo que seja menor ou igual à origem.
case toNearestOrAwayFromZero
Arredonde para o valor permitido mais próximo; se dois valores são igualmente próximos, aquele com maior magnitude é escolhido.
case toNearestOrEven
Arredonde para o valor permitido mais próximo; se dois valores são igualmente próximos, o mesmo é escolhido.
case towardZero
Arredonde para o valor mais próximo permitido, cuja magnitude é menor ou igual à da fonte.
case up
Arredonde para o valor permitido mais próximo que seja maior ou igual à origem.
Utilizamos exemplos semelhantes aos da excelente resposta do @ Suragch para mostrar essas diferentes opções de arredondamento na prática.
.awayFromZero
Arredonde para o valor mais próximo permitido, cuja magnitude é maior ou igual à da fonte; não há equivalente direto entre as funções C, pois isso usa condicionalmente o sinal de self
, ceil
ou floor
, para valores positivos e 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 à floor
função 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 à round
função 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
Essa regra de arredondamento também pode ser acessada usando o rounded()
método de argumento zero .
3.000.rounded() // 3.0
// ...
(-3.000).rounded() // -3.0
// ...
.toNearestOrEven
Arredonde para o valor permitido mais próximo; se dois valores são igualmente próximos, o mesmo é escolhido; equivalente à função C rint
(/ muito semelhante 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 à trunc
função 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 o propósito do arredondamento é para se preparar para o trabalho com um inteiro (por exemplo, usando Int
pela FloatPoint
inicialização após o arredondamento), poderíamos simplesmente fazer uso do fato de que, quando inicializar um Int
usando um Double
(ou Float
etc), a parte decimal será truncado distância.
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 à ceil
função 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
Adendo: visitando o código-fonte para FloatingPoint
verificar a equivalência das funções C às diferentes FloatingPointRoundingRule
regras
Se quisermos, podemos dar uma olhada no código fonte do FloatingPoint
protocolo para ver diretamente a função C equivalente às FloatingPointRoundingRule
regras públicas .
Em swift / stdlib / public / core / FloatingPoint.swift.gyb , vemos que a implementação padrão do rounded(_:)
método nos faz usar o método mutating round(_:)
:
public func rounded(_ rule: FloatingPointRoundingRule) -> Self {
var lhs = self
lhs.round(rule)
return lhs
}
Em swift / stdlib / public / core / FloatingPointTypes.swift.gyb , encontramos a implementação padrão de round(_:)
, na qual a equivalência entre as FloatingPointRoundingRule
regras e as funções de arredondamento C é aparente:
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()
, infelizmente, não disponível em um playground