Swift 3 e 4 - fazendo uso do rounded(_:)método conforme o modelo do FloatingPointprotocolo
O FloatingPointprotocolo (com o qual, por exemplo, Doublee em Floatconformidade) 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, ceilou 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 à floorfunçã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 à roundfunçã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 à truncfunçã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 Intpela FloatPointinicialização após o arredondamento), poderíamos simplesmente fazer uso do fato de que, quando inicializar um Intusando um Double(ou Floatetc), 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 à ceilfunçã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 FloatingPointverificar a equivalência das funções C às diferentes FloatingPointRoundingRuleregras
Se quisermos, podemos dar uma olhada no código fonte do FloatingPointprotocolo para ver diretamente a função C equivalente às FloatingPointRoundingRuleregras 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 FloatingPointRoundingRuleregras 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