Swift - Come rimuovere un decimale da un float se il decimale è uguale a 0?


90

Sto visualizzando una distanza con un decimale e vorrei rimuovere questo decimale nel caso in cui sia uguale a 0 (es: 1200.0Km), come potrei farlo rapidamente? Sto visualizzando questo numero in questo modo:

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

Risposte:


140

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

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

O come estensione:

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

Ho aggiunto questa riga prima distanceFloat = floor(distanceFloat * 10) / 10e poi ha funzionato perfettamente, grazie :)
Kali Aney

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

3
Questo non funzionerà se il float è qualcosa come 3.01.
chengsam

E i numeri negativi?
Happiehappie,

Non funziona per questo numero 123456738.0, il numero convertito è 123456736
Anirudha Mahale,

120

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

Ritorna:

3

5.1

7.21

9.31

600

0,57

0.7


2
Perfetto ! Questo deve essere al top
GoodSp33d

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

1
Che ne dici di 0,3000, provo questo get .3; Ho impostato il suo stileformatter.numberStyle = .decimal
stan liu

@stanliu è corretto, se non si aggiunge il .decimalnumero I numeri di stile inferiori a 1 verranno visualizzati senza zero. Ad esempio: .5, .78, ecc ... Modifica la risposta ora.
HotFudgeDomenica

Credo che questo sia ciò che Apple intende risolvere questo problema.
DragonCherry

55

extension è il modo potente per farlo.

Estensione :

Codice per Swift 2 (non Swift 3 o più recente):

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

Utilizzo :

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

3.234

sampleValue = 3.0
print(sampleValue.cleanValue)

3

sampleValue = 3
print(sampleValue.cleanValue)

3


Il file di esempio di Playground è qui .


1
Ma 3.230000 -> 3.230000 ... che ne dici di "-> 3.23"?
CHiP-love-NY

1
@ CHiP-love-NY, non ti ho capito.
Ashok

1
Credo che pensi che la tua estensione non rimuova gli zeri finali, ma lo fa. String (3.230000) = "3.23"
jeffjv

34

Aggiornamento della risposta accettata per swift 3 :

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

l'utilizzo sarebbe solo:

let someValue: Float = 3.0

print(someValue.cleanValue) //prints 3

Non funziona quando metti ie. 14.000005, si converte in 14.0
Vetuka

@ sc13 Eh, è strano, lo fa se lo spingi fuori a 14.00000005, a quel punto il float stesso restituisce 14 senza 'cleanValue'. Penso che questo abbia qualcosa a che fare con il modo in cui swift gestisce Float. Vado a vedere se riesco a correggere quel bug.
Christopher Larsen,

2
Ottengo l'output corretto per 14.000005, quindi il commento @ sc13 sembra obsoleto o errato.
Cœur

12

Per formattarlo in String, segui questo schema

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"

Per lanciarlo a Int, segui questo schema

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

Quando utilizzi l' String(format:inizializzatore, Swift arrotonda automaticamente l'ultima cifra in base alle necessità in base al numero seguente.


9

Puoi usare un'estensione come già accennato, questa soluzione è un po 'più breve però:

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

Utilizzo di esempio:

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

1
Fallirà per 0.00000001. Consulta la documentazione di% g su pubs.opengroup.org/onlinepubs/009695399/functions/printf.html : " Lo stile utilizzato dipende dal valore convertito; lo stile e (o E) deve essere utilizzato solo se l'esponente risultante da tale conversione è minore di -4 o maggiore o uguale alla precisione. "
Cœur

Perfetto. Grazie
PhillipJacobs

7

In Swift 4 prova questo.

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

// Come si usa: se si immettono più di due caratteri dopo il punto (.), Viene automaticamente ritagliato l'ultimo carattere e vengono visualizzati solo due caratteri dopo il punto.

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

Non taglierà lo zero dal valore 1.1: l'output sarà "1.10".
Cœur

@ Cœur è usato per visualizzare due valori dopo il punto (.). se vuoi visualizzare un solo valore, usa "return self.truncatingRemainder (dividingBy: 1) == 0? String (format:"% .0f ", self): String (format:"% .1f ", self) / / "
Jaydip

Lo so ... stavo solo descrivendo come il tuo codice differisce da un altro comportamento delle risposte.
Cœur

4

NSNumberFormatter è tuo amico

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

Formattazione con numero massimo di cifre frazionarie, senza zeri finali

Questo scenario è utile quando si desidera una precisione di output personalizzata. Questa soluzione sembra più o meno veloce quanto la soluzione NumberFormatter + NSNumber di MirekE , ma un vantaggio potrebbe essere che qui stiamo evitando NSObject.

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

(funziona anche con extension Float, ma non solo per macOS Float80)

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

Uscita per maximumFractionDigits: 2:

1,0 → "1"
0,12 → "0,12"
0,012 → "0,01"
0,0012 → "0"
0,00012 → "0"



4

Swift 5 for Double è uguale alla risposta di @ Frankie per float

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

per l'estensione

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

}

3

Ecco il codice 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

Ecco la riga più importante in profondità.

func displayNumber(number: Float) {
  1. Elimina le cifre decimali del float con Int(number).
  2. Restituisce il numero rimosso in float per eseguire un'operazione Float(Int(number)).
  3. Ottiene il valore della cifra decimale con number - Float(Int(number))
  4. Verifica che il valore della cifra decimale sia vuoto con if number - Float(Int(number)) == 0

Il contenuto all'interno delle istruzioni if ​​e else non necessita di spiegazione.


Nel tuo caso, vorresti che la funzione ritorni Stringe invece di println(result)fare return result. Spero che possa aiutare!
Fine Man

2

Anche questo potrebbe essere utile.

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

Utilizzo:

let number:Float = 45.23230000
number.cleanValue()

-1

Forse stringByReplacingOccurrencesOfStringpotrebbe aiutarti :)

let aFloat: Float = 1.000

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

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

Ciò spezzerebbe un valore come 1.05 -> 15
Starceaker

@Starceaker No, 1.05eseguire String(format: "%.1f", aFloat)prima sarà 1.0, funziona. se verrà 1.05eseguito , e che dovrebbe farloString(format: "%.2f", aFloat)1.05stringByReplacingOccurrencesOfString(".00"...)
Leone

Esatto, mi sono concentrato sull'ultima riga. Pensavo avessi suggerito diverse soluzioni ma in realtà le tue linee sono collegate. Colpa mia.
Starceaker

non è niente :)
Leone
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.