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.