120

I'm displaying a distance with one decimal, and I would like to remove this decimal in case it is equal to 0 (ex: 1200.0Km), how could I do that in swift? I'm displaying this number like this:

let distanceFloat: Float = (currentUser.distance! as NSString).floatValue
distanceLabel.text = String(format: "%.1f", distanceFloat) + "Km"
Kalianey
  • 2,738
  • 6
  • 25
  • 43
  • 1
    Possible duplicate of [Swift - Remove Trailing Zeros From Double](https://stackoverflow.com/questions/29560743/swift-remove-trailing-zeros-from-double) – Cœur Sep 14 '18 at 05:11

15 Answers15

185

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 (Original answer)

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

Or as an extension:

extension Float {
    var clean: String {
        return self % 1 == 0 ? String(format: "%.0f", self) : String(self)
    }
}
l.vasilev
  • 926
  • 2
  • 10
  • 23
Frankie
  • 11,508
  • 5
  • 53
  • 60
156

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

Returns:

3

5.1

7.21

9.31

600

0.57

0.7

HotFudgeSunday
  • 1,403
  • 2
  • 23
  • 29
MirekE
  • 11,515
  • 5
  • 35
  • 28
  • 7
    for Swift 3: ```let formatter = NumberFormatter() formatter.minimumFractionDigits = 0 formatter.maximumFractionDigits = 1 statLabel.text = formatter.string(from: value as NSNumber) ?? "n/a"``` – alexxjk Mar 21 '17 at 18:45
  • 1
    How about 0.3000, I try this get .3; I set its style ```formatter.numberStyle = .decimal``` – stan liu Apr 20 '18 at 08:16
  • @stanliu is correct, if you don't add the `.decimal` numberStyle numbers below 1 will display without a zero. Eg: .5, .78, etc... Editing the answer now. – HotFudgeSunday Jul 09 '18 at 17:46
  • I have this number - 5.7156 but when I used code from this answer then I get output: 5.72. anyone know why? – Ganesh Pawar May 21 '19 at 12:36
  • @GaneshPawar maximumFractionDigits is set to 2 . If you need 4 decimal places set it to 4 – Ankit Kumar Gupta Jul 11 '19 at 07:49
57

extension is the powerful way to do it.

Extension:

Code for Swift 2 (not Swift 3 or newer):

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

Usage:

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

3.234

sampleValue = 3.0
print(sampleValue.cleanValue)

3

sampleValue = 3
print(sampleValue.cleanValue)

3


Sample Playground file is here.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Ashok
  • 5,585
  • 5
  • 52
  • 80
41

Update of accepted answer for swift 3:

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

usage would just be:

let someValue: Float = 3.0

print(someValue.cleanValue) //prints 3
Christopher Larsen
  • 1,375
  • 15
  • 22
22

To format it to String, follow this pattern

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"

To cast it to Int, follow this pattern

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

When you use String(format: initializer, Swift will automatically round the final digit as needed based on the following number.

Baig
  • 4,737
  • 1
  • 32
  • 47
13

Swift 5.5 makes it easy

Just use the new formatted() api with a default FloatingPointFormatStyle:

let values: [Double] = [1.0, 4.5, 100.0, 7]
for value in values {
    print(value.formatted(FloatingPointFormatStyle()))
}
// prints "1, 4.5, 100, 7"
Rohit Makwana
  • 4,337
  • 1
  • 21
  • 29
Trev14
  • 3,626
  • 2
  • 31
  • 40
11

You can use an extension as already mentioned, this solution is a little shorter though:

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

Example usage:

var sample: Float = 3.234
print(sample.shortValue)
Linus
  • 4,643
  • 8
  • 49
  • 74
  • 1
    Will fail for `0.00000001`. See documentation of %g at http://pubs.opengroup.org/onlinepubs/009695399/functions/printf.html: "_The style used depends on the value converted; style e (or E ) shall be used only if the exponent resulting from such a conversion is less than -4 or greater than or equal to the precision._" – Cœur Sep 17 '18 at 01:53
10

Swift 5 for Double it's same as @Frankie's answer for float

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

for the extension

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

}
Mohamed Shaban
  • 2,263
  • 1
  • 15
  • 23
8

In Swift 4 try this.

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

//How to use - if you enter more then two-character after (.)point, it's automatically cropping the last character and only display two characters after the point.

let strValue = "32.12"
print(\(CGFloat(strValue).cleanValue)
Berlin
  • 2,115
  • 2
  • 16
  • 28
  • Will not trim the zero from value `1.1`: output will be `"1.10"`. – Cœur Sep 17 '18 at 02:49
  • @Cœur it's used for display two value after point(.). if you want to display only one value then used " return self.truncatingRemainder(dividingBy: 1) == 0 ? String(format: "%.0f", self) : String(format: "%.1f", self)// " – Berlin Sep 17 '18 at 03:18
  • I know... I was just describing how your code differs from some other answers behavior. – Cœur Sep 17 '18 at 03:26
5

Formatting with maximum fraction digits, without trailing zeros

This scenario is good when a custom output precision is desired. This solution seems roughly as fast as NumberFormatter + NSNumber solution from MirekE, but one benefit could be that we're avoiding NSObject here.

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

(works also with extension Float, but not the macOS-only type Float80)

Usage: myNumericValue.string(maximumFractionDigits: 2) or myNumericValue.string()

Output for maximumFractionDigits: 2:

1.0 → "1"
0.12 → "0.12"
0.012 → "0.01"
0.0012 → "0"
0.00012 → "0"

Community
  • 1
  • 1
Cœur
  • 37,241
  • 25
  • 195
  • 267
5

Simple :

Int(floor(myFloatValue))
ergunkocak
  • 3,334
  • 1
  • 32
  • 31
4

NSNumberFormatter is your friend

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
  • 274,689
  • 30
  • 353
  • 361
3

Here's the full code.

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

Here's the most important line in-depth.

func displayNumber(number: Float) {
  1. Strips the float's decimal digits with Int(number).
  2. Returns the stripped number back to float to do an operation with Float(Int(number)).
  3. Gets the decimal-digit value with number - Float(Int(number))
  4. Checks the decimal-digit value is empty with if number - Float(Int(number)) == 0

The contents within the if and else statements doesn't need explaining.

Fine Man
  • 455
  • 4
  • 17
  • In your case, you'd want to make the function return `String` and instead of the `println(result)` do `return result`. I hope this helps! – Fine Man Jul 14 '15 at 04:41
2

This might be helpful too.

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
  • 363
  • 2
  • 14
0

Maybe stringByReplacingOccurrencesOfString could help you :)

let aFloat: Float = 1.000

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

let wantedString: String = aString.stringByReplacingOccurrencesOfString(".0", withString: "") // "1"
Leo
  • 1,545
  • 13
  • 24
  • This would break a value like 1.05 --> 15 – Starceaker Sep 01 '16 at 17:42
  • @Starceaker No, `1.05` execute `String(format: "%.1f", aFloat)` first will be `1.0`, works. if `1.05` execute `String(format: "%.2f", aFloat)` will be `1.05`, and than should do this `stringByReplacingOccurrencesOfString(".00"...)` – Leo Sep 08 '16 at 10:55