Redondeando un valor doble a x número de decimales en swift
¿Puede alguien decirme cómo redondear un valor doble a x número de decimales en Swift?
Tengo:
var totalWorkTimeInHours = (totalWorkTime/60/60)
Siendo totalWorkTime
un NSTimeInterval (doble) en segundo lugar.
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
?
21 answers
Puede usar la función round
de Swift para lograr esto.
Para redondear a Double
con precisión de 3 dígitos, primero multiplíquelo por 1000, redondéelo y divida el resultado redondeado por 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 de tipo Double
.
EDITAR:
En cuanto a los comentarios que a veces no funciona, por favor lea esto:
Lo Que Todo Científico De La Computación Debe Saber Aritmética de coma flotante
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-28 18:34:26
Extensión para Swift 2
Una solución más general es la siguiente extensión, que funciona con Swift 2 e 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 sustituye 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-16 05:18:43
Usa el constructor String
que toma una cadena format
:
print(String(format: "%.3f", totalWorkTimeInHours))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-01 16:43:30
Con Swift 4, según sus necesidades, puede elegir uno de los 9 siguientes estilos para obtener un resultado redondeado de un Double
.
#1. Usando FloatingPoint
rounded()
método
En el caso más simple, puede utilizar el Double
round()
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(_:)
método
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 Darwin round
Foundation ofrece una función round
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 método personalizado de extensión Double
construido con Darwin round
y pow
funciones
Si desea repetir la operación anterior muchas veces, refactorizar su 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:)
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(_:_:_:_:)
function
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 un NSString
de su operación de redondeo, usar NSString
initializer 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 String
de Swift se puentea con la clase NSString
de Foundation (puede obtener más información al respecto leyendo El Lenguaje de programación Swift). Por lo tanto, puede utilizar el siguiente código en 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 espera 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")
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-16 01:07:08
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-20 10:32:40
Basándose en 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
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-04 11:22:19
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-27 10:45:20
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-19 05:00:06
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 swift que redondee este número a 3 decimales.y si quieres número doble, puedes usar este código:
/ / String to Double
var roundedString = Double(String(format: "%.3f", b))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-04 06:30:24
Un modo práctico puede ser el uso de extensión de 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-11 12:56:43
Utilice la biblioteca incorporada de Foundation 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))
Salidas: 12.988
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-30 23:41:21
Esta es una especie de solución larga, que puede ser útil si sus necesidades son un poco más complejas. Puede utilizar un formateador de números en Swift.
let numberFormatter: NSNumberFormatter = {
let nf = NSNumberFormatter()
nf.numberStyle = .DecimalStyle
nf.minimumFractionDigits = 0
nf.maximumFractionDigits = 1
return nf
}()
Supongamos que la variable que desea imprimir es
var printVar = 3.567
Esto asegurará 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 la OP mencionó la impresión (en cuyo caso una cadena no es indeseable), y porque esta clase permite establecer múltiples parámetros.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-14 22:08:59
Usaría
print(String(format: "%.3f", totalWorkTimeInHours))
Y cambiar .3f a cualquier número de números decimales que necesita
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-27 12:24:59
No es rápido, pero estoy seguro de que entiendes la idea.
pow10np = pow(10,num_places);
val = round(val*pow10np) / pow10np;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-08 00:12:22
Este es un algoritmo más flexible de redondeo 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-07 19:44:13
Redondee 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-21 11:53:24
La mejor manera de formatear una propiedad double 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:
Caso AwayFromZero Redondee al valor permitido más cercano cuya magnitud sea mayor o igual a la de la fuente.
Case down Redondee al valor permitido más cercano que sea menor o igual a la fuente.
Caso Una o dos veces desde Cero Redondea al valor permitido más cercano; si dos valores están igualmente cerca, se elige el de mayor magnitud.
Caso ton Reestoreven Redondee al valor permitido más cercano;si dos valores están igualmente cerca, se elige el par.
Case towardZero Redondee al valor permitido más cercano cuya magnitud sea menor o igual a la de la fuente.
Case up Redondear al valor permitido más cercano que sea mayor que o igual a la fuente.
var aNumber : Double = 5.2
aNumber.rounded(.up) // 6.0
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-05 14:22:55
O bien:
-
Usando
String(format:)
:-
Encasillado
Double
aString
con%.3f
especificador de formato y, a continuación, volver aDouble
Double(String(format: "%.3f", 10.123546789))!
-
O extender
Double
para manejar N-Decimales:extension Double { func rounded(toDecimalPlaces n: Int) -> Double { return Double(String(format: "%.\(n)f", self))! } }
-
-
Por cálculo
-
Multiplicar por 10^3, redondearlo y luego dividir por 10^3...
(1000 * 10.123546789).rounded()/1000
-
O extender
Double
para manejar N-Decimal lugares:extension Double { func rounded(toDecimalPlaces n: Int) -> Double { let multiplier = pow(10, Double(n)) return (multiplier * self).rounded()/multiplier } }
-
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-20 09:39:01
Si desea redondear los valores Double
, es posible que desee usar Swift Decimal
para no introducir ningún error que pueda surgir al intentar matemáticas con estos valores redondeados. Si utiliza Decimal
, puede representar con precisión los valores decimales de ese valor de coma flotante redondeado.
Así que 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 redondeado Decimal
así:
let foo = 427.3000000002
let value = foo.roundedDecimal(to: 2) // results in 427.30
Y si desea mostrarlo con un número especificado de lugares decimales (así como localizar la cadena para el local actual del usuario), puede utilizar un NumberFormatter
:
let formatter = NumberFormatter()
formatter.maximumFractionDigits = 2
formatter.minimumFractionDigits = 2
if let string = formatter.string(for: value) {
print(string)
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-05 07:36:38
Encontré esto preguntándome si es posible corregir la entrada de un usuario. Eso es si ingresan tres decimales en lugar de dos por una cantidad en dólares. Digamos 1.111 en lugar de 1.11 ¿puedes arreglarlo redondeando? La respuesta por muchas razones es no! Con el dinero cualquier cosa sobre es decir 0.001 causaría eventual problemas en una chequera verdadera.
Aquí hay una función para verificar que los usuarios ingresen demasiados valores después del período. Pero que permitirá 1., 1.1 y 1.11.
Se supone que el el valor ya se ha comprobado para la 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
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-06 01:03:59
//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"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-28 09:45:52