Redondear un valor doble a x número de decimales en Swift
¿Alguien puede decirme cómo redondear un valor doble a x número de decimales en Swift?
Tengo:
var totalWorkTimeInHours = (totalWorkTime/60/60)
Con totalWorkTime
ser un NSTimeInterval (doble) en segundo.
totalWorkTimeInHours
me dará las horas, pero me da la cantidad de tiempo en un número tan largo y preciso, por ejemplo 1.543240952039......
¿Cómo redondeo esto a, digamos, 1,543 cuando imprimo totalWorkTimeInHours
?
Puede utilizar round
la función de Swift para lograr esto.
Para redondear a Double
con precisión de 3 dígitos, primero multiplíquelo por 1000, redondeelo y divida el resultado redondeado entre 1000:
let x = 1.23556789
let y = Double(round(1000 * x) / 1000)
print(y) /// 1.236
A diferencia de cualquier tipo printf(...)
de String(format: ...)
solución, el resultado de esta operación sigue siendo de tipo Double
.
Respecto a los comentarios de que a veces no funciona, lea esto: Lo que todo programador debe saber sobre la aritmética de punto flotante
Extensión para Swift 2
Una solución más general es la siguiente extensión, que funciona con Swift 2 y iOS 9:
extension Double {
/// Rounds the double to decimal places value
func roundToPlaces(places:Int) -> Double {
let divisor = pow(10.0, Double(places))
return round(self * divisor) / divisor
}
}
Extensión para Swift 3
En Swift 3 round
se reemplaza por rounded
:
extension Double {
/// Rounds the double to decimal places value
func rounded(toPlaces places:Int) -> Double {
let divisor = pow(10.0, Double(places))
return (self * divisor).rounded() / divisor
}
}
Ejemplo que devuelve Doble redondeado a 4 decimales:
let x = Double(0.123456789).roundToPlaces(4) // x becomes 0.1235 under Swift 2
let x = Double(0.123456789).rounded(toPlaces: 4) // Swift 3 version
¿Cómo redondeo esto a, digamos, 1,543 cuando imprimo
totalWorkTimeInHours
?
Para redondear totalWorkTimeInHours
a 3 dígitos para imprimir, use el String
constructor que toma una format
cadena:
print(String(format: "%.3f", totalWorkTimeInHours))
Con Swift 5, según tus necesidades, puedes elegir uno de los 9 estilos siguientes para tener un resultado redondeado a partir de un archivo Double
.
#1. Usando FloatingPoint
rounded()
el método
En el caso más sencillo, puedes utilizar el Double
rounded()
método.
let roundedValue1 = (0.6844 * 1000).rounded() / 1000
let roundedValue2 = (0.6849 * 1000).rounded() / 1000
print(roundedValue1) // returns 0.684
print(roundedValue2) // returns 0.685
#2. Usando FloatingPoint
rounded(_:)
el método
let roundedValue1 = (0.6844 * 1000).rounded(.toNearestOrEven) / 1000
let roundedValue2 = (0.6849 * 1000).rounded(.toNearestOrEven) / 1000
print(roundedValue1) // returns 0.684
print(roundedValue2) // returns 0.685
#3. Usando round
la función de Darwin
Fundación ofrece una round
función a través de Darwin.
import Foundation
let roundedValue1 = round(0.6844 * 1000) / 1000
let roundedValue2 = round(0.6849 * 1000) / 1000
print(roundedValue1) // returns 0.684
print(roundedValue2) // returns 0.685
#4. Usando un Double
método personalizado de extensión creado con Darwin round
y pow
funciones
Si deseas repetir la operación anterior muchas veces, refactorizar tu código puede ser una buena idea.
import Foundation
extension Double {
func roundToDecimal(_ fractionDigits: Int) -> Double {
let multiplier = pow(10, Double(fractionDigits))
return Darwin.round(self * multiplier) / multiplier
}
}
let roundedValue1 = 0.6844.roundToDecimal(3)
let roundedValue2 = 0.6849.roundToDecimal(3)
print(roundedValue1) // returns 0.684
print(roundedValue2) // returns 0.685
#5. Usando NSDecimalNumber
rounding(accordingToBehavior:)
el método
Si es necesario, NSDecimalNumber
ofrece una solución detallada pero potente para redondear números decimales.
import Foundation
let scale: Int16 = 3
let behavior = NSDecimalNumberHandler(roundingMode: .plain, scale: scale, raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: true)
let roundedValue1 = NSDecimalNumber(value: 0.6844).rounding(accordingToBehavior: behavior)
let roundedValue2 = NSDecimalNumber(value: 0.6849).rounding(accordingToBehavior: behavior)
print(roundedValue1) // returns 0.684
print(roundedValue2) // returns 0.685
#6. Usando NSDecimalRound(_:_:_:_:)
la función
import Foundation
let scale = 3
var value1 = Decimal(0.6844)
var value2 = Decimal(0.6849)
var roundedValue1 = Decimal()
var roundedValue2 = Decimal()
NSDecimalRound(&roundedValue1, &value1, scale, NSDecimalNumber.RoundingMode.plain)
NSDecimalRound(&roundedValue2, &value2, scale, NSDecimalNumber.RoundingMode.plain)
print(roundedValue1) // returns 0.684
print(roundedValue2) // returns 0.685
#7. Usando NSString
init(format:arguments:)
inicializador
Si desea devolver a NSString
de su operación de redondeo, usar NSString
el inicializador es una solución simple pero eficiente.
import Foundation
let roundedValue1 = NSString(format: "%.3f", 0.6844)
let roundedValue2 = NSString(format: "%.3f", 0.6849)
print(roundedValue1) // prints 0.684
print(roundedValue2) // prints 0.685
#8. Usando String
init(format:_:)
inicializador
El tipo de Swift String
está unido a la clase de Foundation NSString
. Por lo tanto, puede utilizar el siguiente código para devolver un valor String
de su operación de redondeo:
import Foundation
let roundedValue1 = String(format: "%.3f", 0.6844)
let roundedValue2 = String(format: "%.3f", 0.6849)
print(roundedValue1) // prints 0.684
print(roundedValue2) // prints 0.685
#9. UsandoNumberFormatter
Si espera obtener un beneficio String?
de su operación de redondeo, NumberFormatter
le ofrecemos una solución altamente personalizable.
import Foundation
let formatter = NumberFormatter()
formatter.numberStyle = NumberFormatter.Style.decimal
formatter.roundingMode = NumberFormatter.RoundingMode.halfUp
formatter.maximumFractionDigits = 3
let roundedValue1 = formatter.string(from: 0.6844)
let roundedValue2 = formatter.string(from: 0.6849)
print(String(describing: roundedValue1)) // prints Optional("0.684")
print(String(describing: roundedValue2)) // prints Optional("0.685")