Swift - ¿Cómo eliminar un decimal de un flotante si el decimal es igual a 0?

88

Estoy mostrando una distancia con un decimal, y me gustaría eliminar este decimal en caso de que sea igual a 0 (por ejemplo: 1200.0Km), ¿cómo podría hacerlo en rápido? Estoy mostrando este número así:

let distanceFloat: Float = (currentUser.distance! as NSString).floatValue
distanceLabel.text = String(format: "%.1f", distanceFloat) + "Km"
Kali Aney
fuente
1
Posible duplicado de Swift - Eliminar ceros finales del doble
Cœur

Respuestas:

137

Rápido 3/4:

var distanceFloat1: Float = 5.0
var distanceFloat2: Float = 5.540
var distanceFloat3: Float = 5.03

extension Float {
    var clean: String {
       return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(self)
    }
}

print("Value \(distanceFloat1.clean)") // 5
print("Value \(distanceFloat2.clean)") // 5.54
print("Value \(distanceFloat3.clean)") // 5.03

Swift 2 (respuesta original)

let distanceFloat: Float = (currentUser.distance! as NSString).floatValue
distanceLabel.text = String(format: distanceFloat == floor(distanceFloat) ? “%.0f" : "%.1f", distanceFloat) + "Km"

O como una extensión:

extension Float {
    var clean: String {
        return self % 1 == 0 ? String(format: "%.0f", self) : String(self)
    }
}
Frankie
fuente
Agregué esta línea antes distanceFloat = floor(distanceFloat * 10) / 10y luego funcionó perfectamente, gracias :)
Kali Aney
1
Para Double, extensión Double {var clean: String {return self% 1 == 0? Cadena (formato: "% .0d", self): String (self)}}
Abo3atef
3
Esto no funcionará si el flotador es algo así como 3.01.
chengsam
¿Qué pasa con los números negativos?
Happiehappie
No funciona para este número 123456738.0, el número convertido viene como 123456736
Anirudha Mahale
116

Utilice NSNumberFormatter:

let formatter = NumberFormatter()
formatter.minimumFractionDigits = 0
formatter.maximumFractionDigits = 2

// Avoid not getting a zero on numbers lower than 1
// Eg: .5, .67, etc...
formatter.numberStyle = .decimal

let nums = [3.0, 5.1, 7.21, 9.311, 600.0, 0.5677, 0.6988]

for num in nums {
    print(formatter.string(from: num as NSNumber) ?? "n/a")
}

Devoluciones:

3

5.1

7.21

9.31

600

0,57

0,7

MirekE
fuente
2
Perfecto ! Esto debe estar en la parte superior
GoodSp33d
6
para Swift 3: let formatter = NumberFormatter() formatter.minimumFractionDigits = 0 formatter.maximumFractionDigits = 1 statLabel.text = formatter.string(from: value as NSNumber) ?? "n/a"
alexxjk
1
¿Qué tal 0.3000, trato de obtener .3; Yo establezco su estiloformatter.numberStyle = .decimal
stan liu
@stanliu es correcto, si no agrega el .decimalnúmero, los números de estilo debajo de 1 se mostrarán sin un cero. Ej .: .5, .78, etc ... Editando la respuesta ahora.
HotFudgeSunday
Creo que esto es lo que Apple intenta resolver tal problema.
DragonCherry
55

extension es la forma poderosa de hacerlo.

Extensión :

Código para Swift 2 (no Swift 3 o más reciente):

extension Float {
    var cleanValue: String {
        return self % 1 == 0 ? String(format: "%.0f", self) : String(self)
    }
}

Uso :

var sampleValue: Float = 3.234
print(sampleValue.cleanValue)

3.234

sampleValue = 3.0
print(sampleValue.cleanValue)

3

sampleValue = 3
print(sampleValue.cleanValue)

3


El archivo de muestra de Playground está aquí .

Ashok
fuente
1
Pero 3.230000 -> 3.230000 ... ¿qué tal "-> 3.23"?
CHiP-love-NY
1
@ CHiP-love-NY, no te entendí.
Ashok
1
Creo que cree que su extensión no elimina los ceros finales, pero lo hace. String (3.230000) = "3.23"
jeffjv
34

Actualización de la respuesta aceptada para swift 3 :

extension Float
{
    var cleanValue: String
    {
        return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(self)
    }
}

el uso sería simplemente:

let someValue: Float = 3.0

print(someValue.cleanValue) //prints 3
Christopher Larsen
fuente
No funciona cuando pones ie. 14.000005, se convierte en 14.0
Vetuka
@ sc13 Eh, eso es extraño, lo hace si lo empuja a 14.00000005, momento en el que el flotador en sí devuelve 14 sin 'cleanValue'. Creo que esto tiene algo que ver con la rapidez con que maneja Float. Voy a ver si puedo arreglar ese error.
Christopher Larsen
2
Obtengo el resultado correcto para 14.000005, por lo que el comentario de @ sc13 parece obsoleto o incorrecto.
Cœur
10

Para formatearlo en String, siga este patrón

let aFloat: Float = 1.123

let aString: String = String(format: "%.0f", aFloat) // "1"
let aString: String = String(format: "%.1f", aFloat) // "1.1"
let aString: String = String(format: "%.2f", aFloat) // "1.12"
let aString: String = String(format: "%.3f", aFloat) // "1.123"

Para lanzarlo a Int, sigue este patrón

let aInt: Int = Int(aFloat) // "1"

Cuando use el String(format:inicializador, Swift redondeará automáticamente el dígito final según sea necesario en función del siguiente número.

Baig
fuente
Esto no funcionará si el valor es 1.678
Saurav Nagpal
@SauravNagpal Funcionará :)
Baig
9

Puede usar una extensión como ya se mencionó, aunque esta solución es un poco más corta:

extension Float {
    var shortValue: String {
        return String(format: "%g", self)
    }
}

Uso de ejemplo:

var sample: Float = 3.234
print(sample.shortValue)
Linus
fuente
1
Fallará por 0.00000001. Consulte la documentación de% g en pubs.opengroup.org/onlinepubs/009695399/functions/printf.html : " El estilo utilizado depende del valor convertido; el estilo e (o E) se utilizará solo si el exponente resultante de dicha conversión es menor que -4 o mayor o igual que la precisión " .
Cœur
Perfecto. Gracias
PhillipJacobs
7

En Swift 4, intente esto.

    extension CGFloat{
        var cleanValue: String{
            //return String(format: 1 == floor(self) ? "%.0f" : "%.2f", self)
            return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(format: "%.2f", self)//
        }
    }

// Cómo se usa: si ingresa más de dos caracteres después del punto (.), Automáticamente se recorta el último carácter y solo se muestran dos caracteres después del punto.

let strValue = "32.12"
print(\(CGFloat(strValue).cleanValue)
Jaydip
fuente
No recortará el cero del valor 1.1: la salida será "1.10".
Cœur
@ Cœur se usa para mostrar dos valores después del punto (.). si desea mostrar solo un valor, utilice "return self.truncatingRemainder (dividingBy: 1) == 0? String (formato:"% .0f ", self): String (formato:"% .1f ", self) / / "
Jaydip
Lo sé ... solo estaba describiendo en qué se diferencia su código de algún otro comportamiento de respuestas.
Cœur
4

NSNumberFormatter es tu amigo

let distanceFloat: Float = (currentUser.distance! as NSString).floatValue
let numberFormatter = NSNumberFormatter()
numberFormatter.positiveFormat = "###0.##"
let distance = numberFormatter.stringFromNumber(NSNumber(float: distanceFloat))!
distanceLabel.text = distance + " Km"
vadian
fuente
4

Formateo con dígitos de fracción máxima, sin ceros finales

Este escenario es bueno cuando se desea una precisión de salida personalizada. Esta solución parece más o menos tan rápida como la solución NumberFormatter + NSNumber de MirekE , pero una ventaja podría ser que estamos evitando NSObject aquí.

extension Double {
    func string(maximumFractionDigits: Int = 2) -> String {
        let s = String(format: "%.\(maximumFractionDigits)f", self)
        var offset = -maximumFractionDigits - 1
        for i in stride(from: 0, to: -maximumFractionDigits, by: -1) {
            if s[s.index(s.endIndex, offsetBy: i - 1)] != "0" {
                offset = i
                break
            }
        }
        return String(s[..<s.index(s.endIndex, offsetBy: offset)])
    }
}

(también funciona con extension Floatel tipo macOS, pero no soloFloat80 )

Uso: myNumericValue.string(maximumFractionDigits: 2) omyNumericValue.string()

Salida para maximumFractionDigits: 2:

1.0 → "1"
0.12 → "0.12"
0.012 → "0.01"
0.0012 → "0"
0.00012 → "0"

Cœur
fuente
4

Swift 5 para Double es lo mismo que la respuesta de @ Frankie para flotar

var dec: Double = 1.0
dec.clean // 1

para la extensión

extension Double {
    var clean: String {
       return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(self)
    }

}
Mohamed Shaban
fuente
3

Aquí está el código completo.

let numberA: Float = 123.456
let numberB: Float = 789.000

func displayNumber(number: Float) {
    if number - Float(Int(number)) == 0 {
        println("\(Int(number))")
    } else {
        println("\(number)")
    }
}

displayNumber(numberA) // console output: 123.456
displayNumber(numberB) // console output: 789

Aquí está la línea más importante en profundidad.

func displayNumber(number: Float) {
  1. Elimina los dígitos decimales del flotador con Int(number) .
  2. Devuelve el número eliminado a flotar para hacer una operación con Float(Int(number)) .
  3. Obtiene el valor de dígito decimal con number - Float(Int(number))
  4. Comprueba que el valor del dígito decimal esté vacío con if number - Float(Int(number)) == 0

No es necesario explicar el contenido de las declaraciones if y else.

Buen hombre
fuente
En su caso, querrá hacer que la función regrese Stringy en lugar de println(result)hacer return result. ¡Espero que esto ayude!
Fine Man
3

Sencillo :

Int(floor(myFloatValue))
ergunkocak
fuente
¿No elimina esto siempre el decimal? OP no quiere eso.
Rakesha Shastri
2

Esto también podría ser útil.

extension Float {
    func cleanValue() -> String {
        let intValue = Int(self)
        if self == 0 {return "0"}
        if self / Float (intValue) == 1 { return "\(intValue)" }
        return "\(self)"
    }
}

Uso:

let number:Float = 45.23230000
number.cleanValue()
Santosh Maharjan
fuente
-1

Quizás stringByReplacingOccurrencesOfStringpueda ayudarte :)

let aFloat: Float = 1.000

let aString: String = String(format: "%.1f", aFloat) // "1.0"

let wantedString: String = aString.stringByReplacingOccurrencesOfString(".0", withString: "") // "1"
León
fuente
Esto rompería un valor como 1.05 -> 15
Starceaker
@Starceaker No, 1.05ejecutar String(format: "%.1f", aFloat)primero será 1.0, funciona. si 1.05ejecutar String(format: "%.2f", aFloat)será 1.05, y que debería hacer estostringByReplacingOccurrencesOfString(".00"...)
Leo
Correcto, me concentré en la última línea. Pensé que sugirió varias soluciones, pero en realidad sus líneas están conectadas. Culpa mía.
Starceaker
eso no es nada :)
Leo