Swift - Como remover um decimal de um float se o decimal for igual a 0?

88

Estou exibindo uma distância com um decimal e gostaria de remover esse decimal caso seja igual a 0 (ex: 1200,0Km), como poderia fazer isso no swift? Estou exibindo este número assim:

let distanceFloat: Float = (currentUser.distance! as NSString).floatValue
distanceLabel.text = String(format: "%.1f", distanceFloat) + "Km"
Kali Aney
fonte
1
Possível duplicata de Swift - Remover Zeros à direita de Double
Cœur

Respostas:

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

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

Ou como uma extensão:

extension Float {
    var clean: String {
        return self % 1 == 0 ? String(format: "%.0f", self) : String(self)
    }
}
Frankie
fonte
Eu adicionei esta linha antes distanceFloat = floor(distanceFloat * 10) / 10e funcionou perfeitamente, obrigado :)
Kali Aney
1
Para Double, extensão Double {var clean: String {return self% 1 == 0? String (formato: "% .0d", self): String (self)}}
Abo3atef
3
Isso não funcionará se o float for algo como 3.01.
chengsam
E quanto aos números negativos?
Happiehappie
Não funciona para este número 123456738.0, o número convertido vem como 123456736
Anirudha Mahale
116

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

Retorna:

3

5,1

7,21

9,31

600

0,57

0,7

MirekE
fonte
2
perfeito! Isso precisa estar no topo
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
Que tal 0,3000, eu tento obter 0,3; Eu defini seu estiloformatter.numberStyle = .decimal
stan liu
@stanliu está correto; se você não adicionar o .decimalnúmero, os números do estilo abaixo de 1 serão exibidos sem um zero. Ex .: 0,5, 0,78, etc ... Editando a resposta agora.
HotFudgeSunday
Eu acredito que é isso que a intenção da apple para resolver esse problema.
DragonCherry
55

extension é a maneira poderosa de fazer isso.

Extensão :

Código para Swift 2 (não Swift 3 ou mais recente):

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


O arquivo de amostra do Playground está aqui .

Ashok
fonte
1
Mas 3,230000 -> 3,230000 ... que tal "-> 3,23"?
CHiP-love-NY
1
@ CHiP-love-NY, não te entendi.
Ashok
1
Acredito que ele pense que sua extensão não remove os zeros à direita, mas remove. String (3.230000) = "3.23"
jeffjv
34

Atualização da resposta aceita para o swift 3 :

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

o uso seria apenas:

let someValue: Float = 3.0

print(someValue.cleanValue) //prints 3
Christopher Larsen
fonte
Não funciona quando você coloca ie. 14.000005, converte para 14.0
Vetuka
@ sc13 Huh, isso é estranho, acontece se você empurrar para 14.00000005, ponto em que o próprio float está retornando 14 sem 'cleanValue'. Acho que isso tem algo a ver com a forma como o Swift lida com Float. Vou ver se consigo consertar esse bug.
Christopher Larsen de
2
Recebo a saída correta para 14,000005, portanto o comentário @ sc13 parece obsoleto ou incorreto.
Cœur
10

Para formatá-lo para String, siga este padrão

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 lançá-lo em Int, siga este padrão

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

Ao usar o String(format:inicializador, o Swift arredondará automaticamente o dígito final conforme necessário com base no seguinte número.

Baig
fonte
Isso não funcionará se o valor for 1,678
Saurav Nagpal
@SauravNagpal Vai funcionar :)
Baig
9

Você pode usar uma extensão como já foi mencionado, mas esta solução é um pouco mais curta:

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

Exemplo de uso:

var sample: Float = 3.234
print(sample.shortValue)
Linus
fonte
1
Irá falhar 0.00000001. Veja a documentação de% g em pubs.opengroup.org/onlinepubs/009695399/functions/printf.html : " O estilo usado depende do valor convertido; o estilo e (ou E) deve ser usado apenas se o expoente resultante de tal conversão é menor que -4 ou maior ou igual à precisão. "
Cœur
perfeito. Obrigado
PhillipJacobs
7

No Swift 4, tente isso.

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

// Como usar - se você inserir mais de dois caracteres após o ponto (.), Ele cortará automaticamente o último caractere e exibirá apenas dois caracteres após o ponto.

let strValue = "32.12"
print(\(CGFloat(strValue).cleanValue)
Jaydip
fonte
Não cortará o zero do valor 1.1: a saída será "1.10".
Cœur
@ Cœur é usado para exibir dois valores após o ponto (.). se você deseja exibir apenas um valor, use "return self.truncatingRemainder (dividingBy: 1) == 0? String (format:"% .0f ", self): String (format:"% .1f ", self) / / "
Jaydip
Eu sei ... Eu estava apenas descrevendo como seu código difere de alguns outros comportamentos de resposta.
Cœur
4

NSNumberFormatter é seu 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"
vadiana
fonte
4

Formatação com dígitos de fração máxima, sem zeros à direita

Este cenário é bom quando uma precisão de saída customizada é desejada. Esta solução parece quase tão rápida quanto a solução NumberFormatter + NSNumber da MirekE , mas um benefício pode ser que estamos evitando NSObject aqui.

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

(funciona também com extension Float, mas não apenas do tipo macOS Float80)

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

Saída para maximumFractionDigits: 2:

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

Cœur
fonte
4

Swift 5 para Double é igual à resposta de @ Frankie para float

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

para a extensão

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

}
Mohamed Shaban
fonte
3

Aqui está o 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

Aqui está a linha mais importante em detalhes.

func displayNumber(number: Float) {
  1. Remove os dígitos decimais do float com Int(number).
  2. Retorna o número retirado para flutuar para fazer uma operação Float(Int(number)).
  3. Obtém o valor do dígito decimal com number - Float(Int(number))
  4. Verifica se o valor do dígito decimal está vazio com if number - Float(Int(number)) == 0

O conteúdo das instruções if e else não precisa de explicação.

Bom homem
fonte
No seu caso, você gostaria de fazer o retorno da função Stringe em vez do println(result)do return result. Eu espero que isso ajude!
Fine Man
3

Simples:

Int(floor(myFloatValue))
Ergunkocak
fonte
Isso não remove sempre o decimal? OP não quer isso.
Rakesha Shastri
2

Isso também pode 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()
Santosh Maharjan
fonte
-1

Talvez stringByReplacingOccurrencesOfStringpossa te ajudar :)

let aFloat: Float = 1.000

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

let wantedString: String = aString.stringByReplacingOccurrencesOfString(".0", withString: "") // "1"
Leo
fonte
Isso quebraria um valor como 1,05 -> 15
Starceaker 01 de
@Starceaker Não, 1.05execute String(format: "%.1f", aFloat)primeiro será 1.0, funciona. se 1.05executar String(format: "%.2f", aFloat)será 1.05, e deve fazer issostringByReplacingOccurrencesOfString(".00"...)
Leo,
Correto, concentrei-me na última linha. Achei que você sugeriu várias soluções, mas na verdade suas linhas estão conectadas. Foi mal.
Starceaker de
isso não é nada :)
Leo