Redondeando un doble valor a x número de decimales en swift

¿Alguien puede decirme cómo redondear un doble valor a x número de decimales en Swift?

Yo tengo:

var totalWorkTimeInHours = (totalWorkTime/60/60) 

Con totalWorkTime es un NSTimeInterval (doble) en el segundo.

totalWorkTimeInHours me dará las horas, pero me da la cantidad de tiempo en un número tan largo, por ejemplo, 1.543240952039 ……

¿Cómo redondeo esto hasta, digamos, 1.543 cuando imprimo totalWorkTimeInHours ?

Puede usar la función round de Swift para lograr esto.

Para redondear un Double con 3 dígitos de precisión, primero multiplíquelo por 1000, redondee y divida el resultado redondeado entre 1000:

 let x = 1.23556789 let y = Double(round(1000*x)/1000) print(y) // 1.236 

Aparte de cualquier tipo de soluciones printf(...) o String(format: ...) , el resultado de esta operación sigue siendo del tipo Double .

EDITAR:
En cuanto a los comentarios que a veces no funciona, lea esto:

Lo que todo informático debería saber sobre la aritmética de coma 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 es reemplazado 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 

Utilice el constructor de String que toma una cadena de format :

 print(String(format: "%.3f", totalWorkTimeInHours)) 

Con Swift 4, de acuerdo con sus necesidades, puede elegir uno de los 9 estilos siguientes para obtener un resultado redondeado de un Double .


# 1. Usando el método rounded() FloatingPoint

En el caso más simple, puede usar el método Double round() .

 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. Usar el método rounded(_:) FloatingPoint

 var roundedValue1 = (0.6844 * 1000).rounded(.toNearestOrEven) / 1000 var roundedValue2 = (0.6849 * 1000).rounded(.toNearestOrEven) / 1000 print(roundedValue1) // returns 0.684 print(roundedValue2) // returns 0.685 

# 3. Usando la función round Darwin

Foundation ofrece una función round 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. Uso de un método personalizado de Double extensión integrado con las funciones round y pow Darwin

Si desea repetir la operación anterior muchas veces, puede ser una buena idea refacturar su código.

 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 el NSDecimalNumber rounding(accordingToBehavior:) NSDecimalNumber rounding(accordingToBehavior:)

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 la función NSDecimalRound(_:_:_:_:)

 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. Usar init(format:arguments:) NSString init(format:arguments:)

Si desea devolver un NSString de su operación de redondeo, usar el inicializador NSString 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. Usar String init(format:_:) initializer

El tipo String de Swift está puenteado con la clase NSString de NSString (para más información, lea el lenguaje de progtwigción Swift ). Por lo tanto, puede usar el siguiente código para devolver un 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. Usando NumberFormatter

Si esperas obtener un String? de su operación de redondeo, NumberFormatter ofrece 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") 

En Swift 2.0 y Xcode 7.2:

 let pi: Double = 3.14159265358979 String(format:"%.2f", pi) 

Ejemplo:

enter image description here

Sobre la base de la respuesta de Yogi, aquí hay una función Swift que hace el trabajo:

 func roundToPlaces(value:Double, places:Int) -> Double { let divisor = pow(10.0, Double(places)) return round(value * divisor) / divisor } 

Este es un código completamente trabajado

Swift 3.0 / 4.0, Xcode 9.0 GM / 9.2

  let doubleValue : Double = 123.32565254455 self.lblValue.text = String(format:"%.f", doubleValue) print(self.lblValue.text) 

salida – 123

  self.lblValue_1.text = String(format:"%.1f", doubleValue) print(self.lblValue_1.text) 

salida – 123.3

  self.lblValue_2.text = String(format:"%.2f", doubleValue) print(self.lblValue_2.text) 

salida – 123.33

  self.lblValue_3.text = String(format:"%.3f", doubleValue) print(self.lblValue_3.text) 

salida – 123.326

En Swift 3.0 y Xcode 8.0:

  extension Double { func roundTo(places: Int) -> Double { let divisor = pow(10.0, Double(places)) return (self * divisor).rounded() / divisor } } 

Usa esta extensión así,

 let doubleValue = 3.567 let roundedValue = doubleValue.roundTo(places: 2) print(roundedValue) // prints 3.56 

El código para dígitos específicos después de decimales es:

 var a = 1.543240952039 var roundedString = String(format: "%.3f", a) 

Aquí, el% .3f le dice al veloz que redondee este número a 3 lugares decimales. Si desea un número doble, puede usar este código:

// Cadena para duplicar

var roundedString = Double(String(format: "%.3f", b))

Una forma práctica puede ser el uso de la extensión del tipo Doble

 extension Double { var roundTo2f: Double {return Double(round(100 *self)/100) } var roundTo3f: Double {return Double(round(1000*self)/1000) } } 

Uso:

 let regularPie: Double = 3.14159 var smallerPie: Double = regularPie.roundTo3f // results 3.142 var smallestPie: Double = regularPie.roundTo2f // results 3.14 

Utilice la biblioteca incorporada de la Fundación Darwin

SWIFT 3

 extension Double { func round(to places: Int) -> Double { let divisor = pow(10.0, Double(places)) return Darwin.round(self * divisor) / divisor } } 

Uso:

 let number:Double = 12.987654321 print(number.round(to: 3)) 

Resultados: 12.988

Este es un tipo de solución larga, que puede ser útil si sus necesidades son un poco más complejas. Puede usar un formateador de números en Swift.

 let numberFormatter: NSNumberFormatter = { let nf = NSNumberFormatter() nf.numberStyle = .DecimalStyle nf.minimumFractionDigits = 0 nf.maximumFractionDigits = 1 return nf }() 

Suponga que su variable que desea imprimir es

 var printVar = 3.567 

Esto se asegurará de que se devuelva en el formato deseado:

 numberFormatter.StringFromNumber(printVar) 

El resultado aquí será “3.6” (redondeado). Si bien esta no es la solución más económica, la doy porque el OP mencionó la impresión (en cuyo caso un String no es indeseable), y porque esta clase permite establecer múltiples parámetros.

yo usaría

 print(String(format: "%.3f", totalWorkTimeInHours)) 

y cambie .3f a cualquier cantidad de números decimales que necesite

Este es el algoritmo más flexible de redondear a N dígitos significativos

Solución Swift 3

 extension Double { // Rounds the double to 'places' significant digits func roundTo(places:Int) -> Double { guard self != 0.0 else { return 0 } let divisor = pow(10.0, Double(places) - ceil(log10(fabs(self)))) return (self * divisor).rounded() / divisor } } // Double(0.123456789).roundTo(places: 2) = 0.12 // Double(1.23456789).roundTo(places: 2) = 1.2 // Double(1234.56789).roundTo(places: 2) = 1200 

redondear un valor doble a x número de decimal
NO. de dígitos después del decimal

 var x = 1.5657676754 var y = (x*10000).rounded()/10000 print(y) // 1.5658 

 var x = 1.5657676754 var y = (x*100).rounded()/100 print(y) // 1.57 

 var x = 1.5657676754 var y = (x*10).rounded()/10 print(y) // 1.6 

No Swift, pero estoy seguro de que entiendes la idea.

 pow10np = pow(10,num_places); val = round(val*pow10np) / pow10np; 

La mejor forma de formatear una propiedad doble es usar los métodos predefinidos de Apple.

 mutating func round(_ rule: FloatingPointRoundingRule) 

FloatingPointRoundingRule es una enumeración que tiene las siguientes posibilidades

Casos de enumeración:

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 que la fuente.

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

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

caso hacia Zero Redondea al valor permitido más cercano cuya magnitud es menor o igual a la de la fuente.

case up Redondea al valor permitido más cercano que sea mayor o igual que la fuente.

 var aNumber : Double = 5.2 aNumber.rounded(.up) // 6.0 

Encontré esto preguntándome si es posible corregir la entrada de un usuario. Eso es si ingresan tres decimales en lugar de dos por un monto en dólares. Digamos 1.111 en vez de 1.11 ¿Puedes arreglarlo redondeando? La respuesta por muchas razones es no! Con dinero por encima de, por ejemplo, 0.001 eventualmente causaría problemas en un talonario de cheques real.

Aquí hay una función para verificar la entrada de los usuarios de demasiados valores después del período. Pero que permitirá 1., 1.1 y 1.11.

Se supone que el valor ya ha sido verificado para una conversión exitosa de una Cadena a un Doble.

 //func need to be where transactionAmount.text is in scope func checkDoublesForOnlyTwoDecimalsOrLess()->Bool{ var theTransactionCharacterMinusThree: Character = "A" var theTransactionCharacterMinusTwo: Character = "A" var theTransactionCharacterMinusOne: Character = "A" var result = false var periodCharacter:Character = "." var myCopyString = transactionAmount.text! if myCopyString.containsString(".") { if( myCopyString.characters.count >= 3){ theTransactionCharacterMinusThree = myCopyString[myCopyString.endIndex.advancedBy(-3)] } if( myCopyString.characters.count >= 2){ theTransactionCharacterMinusTwo = myCopyString[myCopyString.endIndex.advancedBy(-2)] } if( myCopyString.characters.count > 1){ theTransactionCharacterMinusOne = myCopyString[myCopyString.endIndex.advancedBy(-1)] } if theTransactionCharacterMinusThree == periodCharacter { result = true } if theTransactionCharacterMinusTwo == periodCharacter { result = true } if theTransactionCharacterMinusOne == periodCharacter { result = true } }else { //if there is no period and it is a valid double it is good result = true } return result } 

Si desea redondear valores Double , puede utilizar Swift Decimal para no introducir ningún error que pueda surgir al intentar calcular matemáticamente con estos valores redondeados. Si usa Decimal , puede representar con precisión los valores decimales de ese valor de punto flotante redondeado.

Entonces puedes hacer:

 extension Double { /// Convert `Double` to `Decimal`, rounding it to `scale` decimal places. /// /// - Parameters: /// - scale: How many decimal places to round to. Defaults to `0`. /// - mode: The preferred rounding mode. Defaults to `.plain`. /// - Returns: The rounded `Decimal` value. func roundedDecimal(to scale: Int = 0, mode: NSDecimalNumber.RoundingMode = .plain) -> Decimal { var decimalValue = Decimal(self) var result = Decimal() NSDecimalRound(&result, &decimalValue, scale, mode) return result } } 

Entonces, puedes obtener el valor Decimal redondeado de la siguiente manera:

 let foo = 427.3000000002 let value = foo.roundedDecimal(to: 2) // results in 427.30 

Y si desea mostrarlo con un número específico de lugares decimales (así como también localizar la cadena para la configuración regional actual del usuario), puede usar NumberFormatter :

 let formatter = NumberFormatter() formatter.maximumFractionDigits = 2 formatter.minimumFractionDigits = 2 if let string = formatter.string(for: value) { print(string) } 
 //find the distance between two points let coordinateSource = CLLocation(latitude: 30.7717625, longitude:76.5741449 ) let coordinateDestination = CLLocation(latitude: 29.9810859, longitude: 76.5663599) let distanceInMeters = coordinateSource.distance(from: coordinateDestination) let valueInKms = distanceInMeters/1000 let preciseValueUptoThreeDigit = Double(round(1000*valueInKms)/1000) self.lblTotalDistance.text = "Distance is : \(preciseValueUptoThreeDigit) kms" 

Ya sea:

  1. Usando String(format:) :

    • Typecast Double to String con el especificador de formato %.3f y luego de vuelta a Double

       Double(String(format: "%.3f", 10.123546789))! 
    • O extienda Double para manejar lugares N-Decimales:

       extension Double { func rounded(toDecimalPlaces n: Int) -> Double { return Double(String(format: "%.\(n)f", self))! } } 
  2. Por cálculo

    • multiplicar con 10 ^ 3, redondearlo y luego dividir por 10 ^ 3 …

       (1000 * 10.123546789).rounded()/1000 
    • O extienda Double para manejar lugares N-Decimales:

       extension Double { func rounded(toDecimalPlaces n: Int) -> Double { let multiplier = pow(10, Double(n)) return (multiplier * self).rounded()/multiplier } }