Saltar al contenido

¿Cómo redondear un doble al int más cercano en swift?

Hola usuario de nuestro sitio, descubrimos la respuesta a tu pregunta, continúa leyendo y la verás un poco más abajo.

Solución:

Hay un round disponible en el Foundation Biblioteca (en realidad está en Darwin, pero Foundation importaciones Darwin y la mayor parte del tiempo querrás usar Foundation En lugar de usar Darwin directamente).

import Foundation

users = round(users)

Ejecutando su código en un patio de recreo y luego llamando:

print(round(users))

Salidas:

15.0

round() siempre se redondea hacia arriba cuando el lugar decimal es >= .5 y abajo cuando es < .5 (redondeo estándar). Puedes usar floor() para forzar el redondeo hacia abajo, y ceil() para forzar el redondeo.

Si necesita redondear a un lugar específico, multiplique por pow(10.0, number of places), roundy luego dividir por pow(10, number of places):

Redondear a 2 decimales:

let numberOfPlaces = 2.0
let multiplier = pow(10.0, numberOfPlaces)
let num = 10.12345
let rounded = round(num * multiplier) / multiplier
print(rounded)

Salidas:

10.12

Nota: Debido a la forma en que funcionan las matemáticas de punto flotante, rounded puede que no siempre sea perfectamente precisa. Es mejor pensar en ello más como una aproximación al redondeo. Si está haciendo esto con fines de visualización, es mejor usar string formatear para formatear el número en lugar de usar matemáticas para redondearlo.

Para redondear un doble al entero más cercano, simplemente use round().

var x = 3.7
x.round() // x = 4.0

Si no desea modificar el valor original, utilice rounded():

let x = 3.7
let y = x.rounded() // y = 4.0. x = 3.7

Como cabría esperar (o no), un número como 3.5 se redondea hacia arriba y un número como -3.5 se redondea hacia abajo. Si necesita un comportamiento de redondeo diferente, puede utilizar una de las reglas de redondeo. Por ejemplo:

var x = 3.7
x.round(.towardZero) // 3.0

Si necesita un Int luego simplemente tíralo a uno (pero solo si estás seguro de que el Doble no será mayor que Int.max):

let myInt = Int(myDouble.rounded())

Notas

  • Esta respuesta está completamente reescrita. Mi respuesta anterior trataba con las funciones matemáticas de C como round, lround, floor, y ceil. Sin embargo, ahora que Swift tiene esta funcionalidad incorporada, ya no puedo recomendar el uso de esas funciones. Gracias a @dfri por señalarme esto. Echa un vistazo a la excelente respuesta de @ dfri aquí. También hice algo similar para redondear un CGFloat.

Swift 3 y 4: haciendo uso de rounded(_:) método como se muestra en el FloatingPoint protocolo

los FloatingPoint protocolo (al que, por ejemplo, Double y Float cumple) planifica el rounded(_:) método

func rounded(_ rule: FloatingPointRoundingRule) -> Self

Dónde FloatingPointRoundingRule es una enumeración que enumera varias reglas de redondeo diferentes:

case awayFromZero

Redondea al valor permitido más cercano cuya magnitud sea mayor o igual a la de la fuente.

case down

Redondea al valor permitido más cercano que sea menor o igual al origen.

case toNearestOrAwayFromZero

Redondea al valor permitido más cercano; si dos valores son igualmente cercanos, se elige el de mayor magnitud.

case toNearestOrEven

Redondea al valor permitido más cercano; si dos valores son igualmente cercanos, se elige el par.

case towardZero

Redondea al valor permitido más cercano cuya magnitud sea menor o igual a la de la fuente.

case up

Redondea al valor permitido más cercano que sea mayor o igual al origen.

Usamos ejemplos similares a los de la excelente respuesta de @ Suragch para mostrar estas diferentes opciones de redondeo en la práctica.

.awayFromZero

Redondea al valor permitido más cercano cuya magnitud sea mayor o igual a la de la fuente; no hay equivalente directo entre las funciones C, como esto usa, 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 C floor función.

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 C round función.

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 argumento cero rounded() método.

3.000.rounded() // 3.0
// ...

(-3.000).rounded() // -3.0
// ...

.toNearestOrEven

Redondea al valor permitido más cercano; si dos valores son igualmente cercanos, se elige el par; equivalente a la C rint (/muy parecido a nearbyint) función.

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 C trunc función.

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 usando un 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 C ceil función.

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 de FloatingPoint para verificar la equivalencia de las funciones C con las diferentes FloatingPointRoundingRule normas

Si queremos, podemos echar un vistazo al código fuente de FloatingPoint protocolo para ver directamente los equivalentes de la función C al público FloatingPointRoundingRule normas.

Desde swift / stdlib / public / core / FloatingPoint.swift.gyb vemos que la implementación predeterminada del rounded(_:) el método nos hace de la mutación round(_:) método:

public func rounded(_ rule: FloatingPointRoundingRule) -> Self 
    var lhs = self
    lhs.round(rule)
    return lhs

Desde swift / stdlib / public / core / FloatingPointTypes.swift.gyb encontramos la implementación predeterminada de round(_:), en el que la equivalencia entre los FloatingPointRoundingRule reglas y las funciones de redondeo de 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)
    

Si aceptas, tienes la libertad de dejar un escrito acerca de qué le añadirías a esta sección.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *