round - swift 2 decimals
Especificador de formato de cadena de precisión en Swift (29)
Detalles
Xcode 9.3, Swift 4.1
Solución
import Foundation
extension Numeric {
private func _precision(number: NSNumber, precision: Int, roundingMode: NumberFormatter.RoundingMode) -> Self? {
let formatter = NumberFormatter()
formatter.minimumFractionDigits = precision
formatter.roundingMode = roundingMode
if let formatedNumString = formatter.string(from: number), let formatedNum = formatter.number(from: formatedNumString) {
return formatedNum as? Self
}
return nil
}
func precision(_ number: Int, roundingMode: NumberFormatter.RoundingMode = NumberFormatter.RoundingMode.halfUp) -> Self? {
if let num = self as? NSNumber {
return _precision(number: num, precision: number, roundingMode: roundingMode)
}
if let string = self as? String, let double = Double(string) {
return _precision(number: NSNumber(value: double), precision: number, roundingMode: roundingMode)
}
return nil
}
}
Uso
import UIKit
func showInfo<T: Numeric>(value: T) {
print("Type: /(type(of: value))")
print("Original Value: /(value)")
let value1 = value.precision(3)
print("value1 = /(value1 != nil ? "/(value1!)" : "nil")")
let value2 = value.precision(2)
print("value2 = /(value2 != nil ? "/(value2!)" : "nil")")
if let value1 = value1, let value2 = value2 {
print("value1 + value2 = /(value1 + value2)")
}
print("")
}
let double: Double = 232.1987654321
let float = Float(double)
let cgfloat = CGFloat(double)
showInfo(value: double)
showInfo(value: float)
showInfo(value: cgfloat)
Resultado
A continuación se muestra cómo habría truncado un flotante a dos decimales
NSLog(@" %.02f %.02f %.02f", r, g, b);
Revisé los documentos y el libro electrónico, pero no he podido averiguarlo. ¡Gracias!
¿Por qué hacerlo tan complicado? Puedes usar esto en su lugar:
import UIKit
let PI = 3.14159265359
round( PI ) // 3.0 rounded to the nearest decimal
round( PI * 100 ) / 100 //3.14 rounded to the nearest hundredth
round( PI * 1000 ) / 1000 // 3.142 rounded to the nearest thousandth
Véalo trabajar en Playground.
PS: Solución de: http://rrike.sh/xcode/rounding-various-decimal-places-swift/
@Christian Dietrich:
en lugar de:
var k = 1.0
for i in 1...right+1 {
k = 10.0 * k
}
let n = Double(Int(left*k)) / Double(k)
return "/(n)"
también podría ser:
let k = pow(10.0, Double(right))
let n = Double(Int(left*k)) / k
return "/(n)"
[corrección:] Perdón por la confusión * - Por supuesto, esto funciona con dobles. Creo que, lo más práctico (si quieres que los dígitos se redondeen, no que se corten) sería algo así:
infix operator ~> {}
func ~> (left: Double, right: Int) -> Double {
if right <= 0 {
return round(left)
}
let k = pow(10.0, Double(right))
return round(left*k) / k
}
Solo para flotar, simplemente reemplace el doble con flotador, pow con powf y redondee con roundf.
Actualización: encontré que es más práctico usar el tipo de retorno Doble en lugar de Cadena. Funciona igual para la salida de cadena, es decir:
println("Pi is roughly /(3.1415926 ~> 3)")
impresiones: Pi es aproximadamente 3.142
Por lo tanto, puede usarlo de la misma manera para Cadenas (incluso puede escribir: println (d ~> 2)), pero también puede usarlo para redondear valores directamente, es decir:
d = Double(slider.value) ~> 2
o lo que necesites ...
Aún puede usar NSLog en Swift como en Objective-C solo sin el signo @.
NSLog("%.02f %.02f %.02f", r, g, b)
Edit: Después de trabajar con Swift desde hace un tiempo, me gustaría agregar también esta variación
var r=1.2
var g=1.3
var b=1.4
NSLog("/(r) /(g) /(b)")
Salida:
2014-12-07 21:00:42.128 MyApp[1626:60b] 1.2 1.3 1.4
Aquí una solución rápida "pura"
var d = 1.234567
operator infix ~> {}
@infix func ~> (left: Double, right: Int) -> String {
if right == 0 {
return "/(Int(left))"
}
var k = 1.0
for i in 1..right+1 {
k = 10.0 * k
}
let n = Double(Int(left*k)) / Double(k)
return "/(n)"
}
println("/(d~>2)")
println("/(d~>1)")
println("/(d~>0)")
Ejemplo de Swift2: ancho de pantalla del dispositivo iOS que formatea el flotador eliminando el decimal
print(NSString(format: "Screen width = %.0f pixels", CGRectGetWidth(self.view.frame)))
Encontré que String.localizedStringWithFormat
funciona bastante bien:
Ejemplo:
let value: Float = 0.33333
let unit: String = "mph"
yourUILabel.text = String.localizedStringWithFormat("%.2f %@", value, unit)
Esta es una forma muy rápida y sencilla de no necesitar una solución compleja.
let duration = String(format: "%.01f", 3.32323242)
// result = 3.3
La mayoría de las respuestas aquí son válidas. Sin embargo, en caso de que formatee el número a menudo, considere la posibilidad de ampliar la clase Float para agregar un método que devuelva una cadena con formato. Ver código de ejemplo a continuación. Éste logra el mismo objetivo utilizando un formateador de números y una extensión.
extension Float {
func string(fractionDigits:Int) -> String {
let formatter = NSNumberFormatter()
formatter.minimumFractionDigits = fractionDigits
formatter.maximumFractionDigits = fractionDigits
return formatter.stringFromNumber(self) ?? "/(self)"
}
}
let myVelocity:Float = 12.32982342034
println("The velocity is /(myVelocity.string(2))")
println("The velocity is /(myVelocity.string(1))")
La consola muestra:
The velocity is 12.33
The velocity is 12.3
Actualización SWIFT 3.1
extension Float {
func string(fractionDigits:Int) -> String {
let formatter = NumberFormatter()
formatter.minimumFractionDigits = fractionDigits
formatter.maximumFractionDigits = fractionDigits
return formatter.string(from: NSNumber(value: self)) ?? "/(self)"
}
}
Las respuestas proporcionadas hasta ahora que han recibido la mayoría de los votos dependen de los métodos de NSString y requerirán que haya importado Foundation.
Sin embargo, una vez hecho esto, todavía tiene acceso a NSLog.
Entonces, creo que la respuesta a la pregunta, si está preguntando cómo continuar usando NSLog en Swift, es simplemente:
import Foundation
Mi mejor solución hasta ahora, siguiendo la respuesta de David :
import Foundation
extension Int {
func format(f: String) -> String {
return String(format: "%/(f)d", self)
}
}
extension Double {
func format(f: String) -> String {
return String(format: "%/(f)f", self)
}
}
let someInt = 4, someIntFormat = "03"
println("The integer number /(someInt) formatted with /"/(someIntFormat)/" looks like /(someInt.format(someIntFormat))")
// The integer number 4 formatted with "03" looks like 004
let someDouble = 3.14159265359, someDoubleFormat = ".3"
println("The floating point number /(someDouble) formatted with /"/(someDoubleFormat)/" looks like /(someDouble.format(someDoubleFormat))")
// The floating point number 3.14159265359 formatted with ".3" looks like 3.142
Creo que esta es la solución más rápida, que vincula las operaciones de formato directamente al tipo de datos. Bien puede ser que haya una biblioteca incorporada de operaciones de formato en algún lugar, o tal vez se publique pronto. Tenga en cuenta que el lenguaje todavía está en beta.
Muchas buenas respuestas anteriores, pero a veces un patrón es más apropiado que el tipo "% .3f" de engulido. Aquí está mi opinión sobre el uso de un NumberFormatter en Swift 3.
extension Double {
func format(_ pattern: String) -> String {
let formatter = NumberFormatter()
formatter.format = pattern
return formatter.string(from: NSNumber(value: self))!
}
}
let n1 = 0.350, n2 = 0.355
print(n1.format("0.00#")) // 0.35
print(n2.format("0.00#")) // 0.355
Aquí quería que siempre se mostraran 2 decimales, pero el tercero solo si no era cero.
No puedes hacerlo (todavía) con interpolación de cadenas. Su mejor apuesta todavía será el formato NSString:
println(NSString(format:"%.2f", sqrt(2.0)))
Extrapolando de python, parece que una sintaxis razonable podría ser:
@infix func % (value:Double, format:String) -> String {
return NSString(format:format, value)
}
Lo que luego te permite usarlos como:
M_PI % "%5.3f" // "3.142"
Puede definir operadores similares para todos los tipos numéricos, desafortunadamente no he encontrado una manera de hacerlo con genéricos.
No sé acerca de dos lugares decimales, pero aquí es cómo puede imprimir flotantes con cero lugares decimales, así que me imagino que pueden ser 2 lugares, 3, lugares ... (Nota: debe convertir CGFloat a Doble para pasar a Cadena (formato :) o verá un valor de cero)
func logRect(r: CGRect, _ title: String = "") {
println(String(format: "[ (%.0f, %.0f), (%.0f, %.0f) ] %@",
Double(r.origin.x), Double(r.origin.y), Double(r.size.width), Double(r.size.height), title))
}
Poder de extensión
extension Double {
var asNumber:String {
if self >= 0 {
var formatter = NSNumberFormatter()
formatter.numberStyle = .NoStyle
formatter.percentSymbol = ""
formatter.maximumFractionDigits = 1
return "/(formatter.stringFromNumber(self)!)"
}
return ""
}
}
let velocity:Float = 12.32982342034
println("The velocity is /(velocity.toNumber)")
Salida: La velocidad es 12.3.
Swift 4
let string = String(format: "%.2f", locale: Locale.current, arguments: 15.123)
También con redondeo:
extension Float
{
func format(f: String) -> String
{
return NSString(format: "%/(f)f", self)
}
mutating func roundTo(f: String)
{
self = NSString(format: "%/(f)f", self).floatValue
}
}
extension Double
{
func format(f: String) -> String
{
return NSString(format: "%/(f)f", self)
}
mutating func roundTo(f: String)
{
self = NSString(format: "%/(f)f", self).doubleValue
}
}
x = 0.90695652173913
x.roundTo(".2")
println(x) //0.91
También puedes crear un operador de esta manera.
operator infix <- {}
func <- (format: String, args:[CVarArg]) -> String {
return String(format: format, arguments: args)
}
let str = "%d %.1f" <- [1453, 1.123]
Una forma simple es:
print(String(format: "hex string: %X", 123456))
print(String(format: "a float number: %.5f", 1.0321))
Una solución más elegante y genérica es reescribir el operador ruby / python %
:
// Updated for beta 5
func %(format:String, args:[CVarArgType]) -> String {
return NSString(format:format, arguments:getVaList(args))
}
"Hello %@, This is pi : %.2f" % ["World", M_PI]
Una versión del operador ruby / python% de Vincent Guerci, actualizada para Swift 2.1:
func %(format:String, args:[CVarArgType]) -> String {
return String(format:format, arguments:args)
}
"Hello %@, This is pi : %.2f" % ["World", M_PI]
menos forma de escribir:
func fprint(format: String, _ args: CVarArgType...) {
print(NSString(format: format, arguments: getVaList(args)))
}
usar el método de abajo
let output = String.localizedStringWithFormat(" %.02f %.02f %.02f", r, g, b)
println(output)
utilizar
CGFloat
o
Float.roundTo(places:2)
Swift 4 Xcode 10 Update
extension Double {
var asNumber:String {
if self >= 0 {
let formatter = NumberFormatter()
formatter.numberStyle = .none
formatter.percentSymbol = ""
formatter.maximumFractionDigits = 2
return "/(formatter.string(from: NSNumber(value: self)) ?? "")"
}
return ""
}
}
//It will more help, by specify how much decimal Point you want.
let decimalPoint = 2
let floatAmount = 1.10001
let amountValue = String(format: "%0.*f", decimalPoint, floatAmount)
@infix func ^(left:Double, right: Int) -> NSNumber {
let nf = NSNumberFormatter()
nf.maximumSignificantDigits = Int(right)
return nf.numberFromString(nf.stringFromNumber(left))
}
let r = 0.52264
let g = 0.22643
let b = 0.94837
println("this is a color: /(r^3) /(g^3) /(b^3)")
// this is a color: 0.523 0.226 0.948
extension Double {
func formatWithDecimalPlaces(decimalPlaces: Int) -> Double {
let formattedString = NSString(format: "%./(decimalPlaces)f", self) as String
return Double(formattedString)!
}
}
1.3333.formatWithDecimalPlaces(2)
import Foundation
extension CGFloat {
var string1: String {
return String(format: "%.1f", self)
}
var string2: String {
return String(format: "%.2f", self)
}
}
Uso
let offset = CGPoint(1.23, 4.56)
print("offset: /(offset.x.string1) x /(offset.y.string1)")
// offset: 1.2 x 4.6