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"
Kali Aney
la source
1
Double
Cœur

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)
    }
}
Frankie
la source
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

MirekE
la source
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 .

Ashok
la source
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
Christopher Larsen
la source
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.

Baig
la source
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)
Linus
la source
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)
Jaydip
la source
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"
vadian
la source
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»

Cœur
la source
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)
    }

}
Mohamed Shaban
la source
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é.

Brave homme
la source
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
3

Facile :

Int(floor(myFloatValue))
ergunkocak
la source
Cela ne supprime-t-il pas toujours la décimale? OP ne veut pas de ça.
Rakesha Shastri le
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()
Santosh Maharjan
la source
-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"
Leo
la source
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