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"

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)
    }
}

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


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í .


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

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.


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)

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)

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"

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"


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)
    }

}

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.


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


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()

-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"

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.