Swift - Jak usunąć przecinek z wartości zmiennoprzecinkowej, jeśli liczba dziesiętna jest równa 0?

88

Wyświetlam odległość z jednym miejscem po przecinku i chciałbym usunąć ten dziesiętny, jeśli jest równy 0 (np. 1200,0 km), jak mogę to zrobić szybko? Wyświetlam ten numer w ten sposób:

let distanceFloat: Float = (currentUser.distance! as NSString).floatValue
distanceLabel.text = String(format: "%.1f", distanceFloat) + "Km"
Kali Aney
źródło
1
Możliwy duplikat Swifta - Usuń końcowe zera z Double
Cœur

Odpowiedzi:

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 (oryginalna odpowiedź)

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

Lub jako rozszerzenie:

extension Float {
    var clean: String {
        return self % 1 == 0 ? String(format: "%.0f", self) : String(self)
    }
}
Frankie
źródło
Dodałem tę linię wcześniej, distanceFloat = floor(distanceFloat * 10) / 10a potem działało idealnie, dzięki :)
Kali Aney
1
Dla Double, rozszerzenie Double {var clean: String {return self% 1 == 0? String (format: „% .0d”, self): String (self)}}
Abo3atef
3
To nie zadziała, jeśli liczba zmiennoprzecinkowa jest podobna do 3.01.
chengsam
A co z liczbami ujemnymi?
Happiehappie
To nie działa dla tego numeru 123456738.0, przekonwertowana liczba to 123456736
Anirudha Mahale
116

Użyj 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")
}

Zwroty:

3

5.1

7.21

9.31

600

0.57

0,7

MirekE
źródło
2
idealny ! To musi być na topie
GoodSp33d
6
dla Swift 3: let formatter = NumberFormatter() formatter.minimumFractionDigits = 0 formatter.maximumFractionDigits = 1 statLabel.text = formatter.string(from: value as NSNumber) ?? "n/a"
alexxjk
1
Co powiesz na 0,3000, próbuję to uzyskać .3; Ustanowiłem jego stylformatter.numberStyle = .decimal
stan liu
@stanliu jest poprawne, jeśli nie dodasz .decimalnumeru NumberStyle poniżej 1 wyświetlą się bez zera. Np .: .5, .78, itd ... Edytujemy teraz odpowiedź.
HotFudgeSunday
Myślę, że właśnie to zamierza rozwiązać Apple.
DragonCherry
55

extension to potężny sposób, aby to zrobić.

Rozszerzenie :

Kod Swift 2 (nie Swift 3 ani nowszy):

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

Użycie :

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

3.234

sampleValue = 3.0
print(sampleValue.cleanValue)

3

sampleValue = 3
print(sampleValue.cleanValue)

3


Przykładowy plik Playground jest tutaj .

Ashok
źródło
1
Ale 3,230000 -> 3,230000 ... co powiesz na „-> 3,23”?
CHiP-love-NY
1
@ CHiP-love-NY, nie rozumiem cię.
Ashok
1
Myślę, że on myśli, że twoje rozszerzenie nie usuwa zer końcowych, ale tak jest. String (3.230000) = "3,23"
jeffjv
34

Aktualizacja zaakceptowanej odpowiedzi dla Swift 3 :

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

użycie byłoby po prostu:

let someValue: Float = 3.0

print(someValue.cleanValue) //prints 3
Christopher Larsen
źródło
Nie działa, gdy włożysz np. 14.000005, konwertuje do 14.0
Vetuka
@ sc13 Huh, to dziwne, dzieje się, jeśli wypchniesz go do 14.00000005, w którym to momencie sam float zwraca 14 bez „cleanValue”. Myślę, że ma to coś wspólnego z szybkością obsługi Float. Sprawdzę, czy mogę naprawić ten błąd.
Christopher Larsen
2
Otrzymuję prawidłowe dane wyjściowe dla 14.000005, więc komentarz @ sc13 wydaje się przestarzały lub niepoprawny.
Cœur,
10

Aby sformatować go na ciąg, postępuj zgodnie z tym wzorcem

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"

Aby rzucić to na Int, postępuj zgodnie z tym wzorcem

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

Gdy używasz String(format:inicjatora, Swift automatycznie zaokrągli ostatnią cyfrę w razie potrzeby na podstawie następującej liczby.

Baig
źródło
To nie zadziała, jeśli wartość wynosi 1,678
Saurav Nagpal
@SauravNagpal To zadziała :)
Baig
9

Możesz użyć rozszerzenia, jak już wspomniano, to rozwiązanie jest jednak trochę krótsze:

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

Przykładowe użycie:

var sample: Float = 3.234
print(sample.shortValue)
Linus
źródło
1
Nie uda się 0.00000001. Zobacz dokumentację% g na pubs.opengroup.org/onlinepubs/009695399/functions/printf.html : „ Zastosowany styl zależy od przekonwertowanej wartości; styl e (lub E) powinien być używany tylko wtedy, gdy wykładnik będący wynikiem takiej konwersji jest mniejsza niż -4 lub większa lub równa precyzji.
Cœur
idealny. Dzięki
PhillipJacobs
7

W Swift 4 spróbuj tego.

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

// Jak używać - jeśli wprowadzisz więcej niż dwa znaki po (.) Punkcie, automatycznie przycina ostatni znak i wyświetla tylko dwa znaki po punkcie.

let strValue = "32.12"
print(\(CGFloat(strValue).cleanValue)
Jaydip
źródło
Nie przycina zera od wartości 1.1: wyjście będzie "1.10".
Cœur,
@ Cœur służy do wyświetlania dwóch wartości po punkcie (.). jeśli chcesz wyświetlić tylko jedną wartość, użyj "return self.truncatingRemainder (dividingBy: 1) == 0? String (format:"% .0f ", self): String (format:"% .1f ", self) / / "
Jaydip,
Wiem ... Właśnie opisywałem, jak twój kod różni się od niektórych innych odpowiedzi.
Cœur,
4

NSNumberFormatter to Twój przyjaciel

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
źródło
4

Formatowanie z maksymalną liczbą cyfr po przecinku, bez końcowych zer

Ten scenariusz jest dobry, gdy wymagana jest niestandardowa precyzja wyjściowa. To rozwiązanie wydaje się mniej więcej tak szybkie, jak rozwiązanie NumberFormatter + NSNumber firmy MirekE , ale jedną z korzyści może być to, że unikamy tutaj 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)])
    }
}

(działa również z extension Floattypem macOS, ale nie działa Float80)

Sposób użycia: myNumericValue.string(maximumFractionDigits: 2)lubmyNumericValue.string()

Wyjście dla maximumFractionDigits: 2:

1,0 → „1”
0,12 → „0,12”
0,012 → „0,01”
0,0012 → „0”
0,00012 → „0”

Cœur
źródło
4

Swift 5 for Double to to samo, co odpowiedź @ Frankie na float

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

na rozszerzenie

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

}
Mohamed Shaban
źródło
3

Oto pełny kod.

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

Oto najważniejsze szczegółowe omówienie linii.

func displayNumber(number: Float) {
  1. Usuwa cyfry dziesiętne pływaka za pomocą Int(number).
  2. Zwraca usuniętą liczbę z powrotem do wartości zmiennoprzecinkowej, na której można wykonać operację Float(Int(number)).
  3. Pobiera wartość cyfry dziesiętnej z number - Float(Int(number))
  4. Sprawdza, czy wartość cyfry dziesiętnej jest pusta za pomocą if number - Float(Int(number)) == 0

Treść instrukcji if i else nie wymaga wyjaśnienia.

Dobry człowiek
źródło
W twoim przypadku chciałbyś, aby funkcja zwracała, Stringa zamiast println(result)do return result. Mam nadzieję, że to pomoże!
Fine Man,
3

Prosty :

Int(floor(myFloatValue))
ergunkocak
źródło
Czy to nie zawsze usuwa ułamek dziesiętny? OP tego nie chce.
Rakesha Shastri
2

To też może być pomocne.

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

Stosowanie:

let number:Float = 45.23230000
number.cleanValue()
Santosh Maharjan
źródło
-1

Może stringByReplacingOccurrencesOfStringmógłby ci pomóc :)

let aFloat: Float = 1.000

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

let wantedString: String = aString.stringByReplacingOccurrencesOfString(".0", withString: "") // "1"
Lew
źródło
To przełamałoby wartość taką jak 1,05 -> 15
Starceaker
@Starceaker Nie, 1.05wykonaj String(format: "%.1f", aFloat)najpierw będzie 1.0, działa. jeśli 1.05wykonanie String(format: "%.2f", aFloat)będzie 1.05, a niż powinno to zrobićstringByReplacingOccurrencesOfString(".00"...)
Leo
Prawidłowo, skupiłem się na ostatniej linii. Myślałem, że zaproponowałeś kilka rozwiązań, ale w rzeczywistości twoje linie są połączone. Mój błąd.
Starceaker
to nic :)
Leo