Swift - Comment supprimer une décimale d'un flottant si la décimale est égale à 0?


88

J'affiche une distance avec une décimale, et je voudrais supprimer cette décimale au cas où elle serait égale à 0 (ex: 1200.0Km), comment pourrais-je faire cela en Swift? J'affiche ce numéro comme ceci:

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

Réponses:


137

Swift 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 (réponse originale)

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

Ou en extension:

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

J'ai ajouté cette ligne avant distanceFloat = floor(distanceFloat * 10) / 10et cela a fonctionné parfaitement, merci :)
Kali Aney

1
Pour Double, extension Double {var clean: String {return self% 1 == 0? String (format: "% .0d", self): String (self)}}
Abo3atef

3
Cela ne fonctionnera pas si le flotteur est quelque chose comme 3.01.
chengsam le

Et les nombres négatifs?
Happiehappie

Cela ne fonctionne pas pour ce numéro 123456738.0, le nombre converti est 123456736
Anirudha Mahale

116

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

Retour:

3

5.1

7,21

9,31

600

0,57

0,7


2
parfait! Cela doit être au top
GoodSp33d

6
pour Swift 3: let formatter = NumberFormatter() formatter.minimumFractionDigits = 0 formatter.maximumFractionDigits = 1 statLabel.text = formatter.string(from: value as NSNumber) ?? "n/a"
alexxjk

1
Que diriez-vous de 0,3000, j'essaie d'obtenir 0,3; J'ai mis son styleformatter.numberStyle = .decimal
stan liu

@stanliu est correct, si vous n'ajoutez pas les .decimalnombres numberStyle inférieurs à 1 s'afficheront sans zéro. Ex: .5, .78, etc ... Modification de la réponse maintenant.
HotFudgeSunday

Je crois que c'est ce qu'Apple a l'intention de résoudre ce problème.
DragonCherry

55

extension est le moyen puissant de le faire.

Extension :

Code pour Swift 2 (pas Swift 3 ou plus récent):

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

Utilisation :

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

3,234

sampleValue = 3.0
print(sampleValue.cleanValue)

3

sampleValue = 3
print(sampleValue.cleanValue)

3


Un exemple de fichier Playground est ici .


1
Mais 3.230000 -> 3.230000 ... que diriez-vous de "-> 3.23"?
CHiP-love-NY

1
@ CHiP-love-NY, je ne vous ai pas compris.
Ashok

1
Je crois qu'il pense que votre extension ne supprime pas les zéros de fin, mais c'est le cas. String (3.230000) = "3.23"
jeffjv

34

Mise à jour de la réponse acceptée pour swift 3 :

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

l'utilisation serait juste:

let someValue: Float = 3.0

print(someValue.cleanValue) //prints 3

Ne fonctionne pas lorsque vous mettez ie. 14.000005, il se convertit en 14.0
Vetuka

@ sc13 Huh, c'est bizarre, c'est le cas si vous le poussez à 14.00000005, auquel point le flotteur lui-même renvoie 14 sans «cleanValue». Pensez que cela a quelque chose à voir avec la rapidité avec laquelle Float gère. Je vais voir si je peux corriger ce bogue.
Christopher Larsen

2
J'obtiens la sortie correcte pour 14.000005, donc le commentaire @ sc13 semble obsolète ou incorrect.
Cœur

10

Pour le formater en chaîne, suivez ce modèle

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"

Pour le convertir en Int, suivez ce modèle

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

Lorsque vous utilisez l' String(format:initialiseur, Swift arrondira automatiquement le dernier chiffre selon les besoins en fonction du nombre suivant.


Cela ne fonctionnera pas si la valeur est 1.678
Saurav Nagpal

@SauravNagpal Cela fonctionnera :)
Baig

9

Vous pouvez utiliser une extension comme déjà mentionné, cette solution est cependant un peu plus courte:

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

Exemple d'utilisation:

var sample: Float = 3.234
print(sample.shortValue)

1
Va échouer pour 0.00000001. Voir la documentation de% g sur pubs.opengroup.org/onlinepubs/009695399/functions/printf.html : " Le style utilisé dépend de la valeur convertie; le style e (ou E) ne sera utilisé que si l'exposant résultant d'une telle conversion est inférieur à -4 ou supérieur ou égal à la précision. "
Cœur

parfait. Merci
PhillipJacobs

7

Dans Swift 4, essayez ceci.

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

// Comment utiliser - si vous entrez plus de deux caractères après le point (.), Il recadre automatiquement le dernier caractère et n'affiche que deux caractères après le point.

let strValue = "32.12"
print(\(CGFloat(strValue).cleanValue)

Ne coupera pas le zéro de la valeur 1.1: la sortie sera "1.10".
Cœur du

@ Cœur est utilisé pour afficher deux valeurs après le point (.). si vous ne voulez afficher qu'une seule valeur alors utilisé "return self.truncatingRemainder (divisionBy: 1) == 0? String (format:"% .0f ", self): String (format:"% .1f ", self) / / "
Jaydip

Je sais ... Je décrivais juste en quoi votre code diffère de certains autres comportements de réponse.
Cœur

4

NSNumberFormatter est votre ami

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

Formatage avec des chiffres de fraction maximum, sans zéros de fin

Ce scénario est bon lorsqu'une précision de sortie personnalisée est souhaitée. Cette solution semble à peu près aussi rapide que la solution NumberFormatter + NSNumber de MirekE , mais un avantage pourrait être que nous évitons NSObject ici.

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

(fonctionne également avec extension Float, mais pas uniquement avec le type macOS Float80)

Utilisation: myNumericValue.string(maximumFractionDigits: 2)oumyNumericValue.string()

Sortie pour maximumFractionDigits: 2:

1,0 → «1»
0,12 → «0,12»
0,012 → «0,01»
0,0012 → «0»
0,00012 → «0»


4

Swift 5 pour Double c'est la même chose que la réponse de @ Frankie pour float

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

pour l'extension

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

}

3

Voici le code complet.

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

Voici la ligne la plus importante en profondeur.

func displayNumber(number: Float) {
  1. Supprime les chiffres décimaux du flotteur avec Int(number).
  2. Renvoie le nombre dépouillé en float pour effectuer une opération avec Float(Int(number)).
  3. Obtient la valeur décimale avec number - Float(Int(number))
  4. Vérifie que la valeur décimale est vide avec if number - Float(Int(number)) == 0

Le contenu des instructions if et else n'a pas besoin d'être expliqué.


Dans votre cas, vous voudriez que la fonction retourne Stringet au lieu de println(result)faire return result. J'espère que ça aide!
Fine Man


2

Cela pourrait aussi être utile.

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

Usage:

let number:Float = 45.23230000
number.cleanValue()

-1

Peut stringByReplacingOccurrencesOfString- être pourrait vous aider :)

let aFloat: Float = 1.000

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

let wantedString: String = aString.stringByReplacingOccurrencesOfString(".0", withString: "") // "1"

Cela briserait une valeur comme 1.05 -> 15
Starceaker

@Starceaker Non, 1.05exécutez en String(format: "%.1f", aFloat)premier sera 1.0, fonctionne. si 1.05exécuter String(format: "%.2f", aFloat)sera 1.05, et que devrait le fairestringByReplacingOccurrencesOfString(".00"...)
Leo

Correct, je me suis concentré sur la dernière ligne. Je pensais que vous aviez suggéré plusieurs solutions mais en fait vos lignes sont connectées. Ma faute.
Starceaker

ce n'est rien :)
Leo
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.