Swift 4: Formatting number's into friendly K's

This answer formats by truncating (versus rounding). 1,515 rounded would generate 2k whereas truncated would generate 1.5k. The function requires reducing a number's scale (removing digits to the right of the decimal) which I've just packaged as an extension so it can be used anywhere (not just in the function).

extension Double {
    func reduceScale(to places: Int) -> Double {
        let multiplier = pow(10, Double(places))
        let newDecimal = multiplier * self // move the decimal right
        let truncated = Double(Int(newDecimal)) // drop the fraction
        let originalDecimal = truncated / multiplier // move the decimal back
        return originalDecimal
    }
}

func formatNumber(_ n: Int) -> String {
    let num = abs(Double(n))
    let sign = (n < 0) ? "-" : ""

    switch num {
    case 1_000_000_000...:
        var formatted = num / 1_000_000_000
        formatted = formatted.reduceScale(to: 1)
        return "\(sign)\(formatted)B"

    case 1_000_000...:
        var formatted = num / 1_000_000
        formatted = formatted.reduceScale(to: 1)
        return "\(sign)\(formatted)M"

    case 1_000...:
        var formatted = num / 1_000
        formatted = formatted.reduceScale(to: 1)
        return "\(sign)\(formatted)K"

    case 0...:
        return "\(n)"

    default:
        return "\(sign)\(n)"
    }
}

You can fine tune this method for specific cases, such as returning 100k instead of 100.5k or 1M instead of 1.1M. This method handles negatives as well.

print(formatNumber(1515)) // 1.5K
print(formatNumber(999999)) // 999.9K
print(formatNumber(1000999)) // 1.0M

The following logic of if-else statements shows you what goes first and what last:

func formatPoints(from: Int) -> String {

    let number = Double(from)
    let thousand = number / 1000
    let million = number / 1000000
    let billion = number / 1000000000

    if billion >= 1.0 {
        return "\(round(billion*10)/10)B"
    } else if million >= 1.0 {
        return "\(round(million*10)/10)M"
    } else if thousand >= 1.0 {
        return ("\(round(thousand*10/10))K")
    } else {
        return "\(Int(number))"
    }
}

print(formatPoints(1000))             /*  1.0 K  */
print(formatPoints(1000000))          /*  1.0 M  */
print(formatPoints(1000000000))       /*  1.0 B  */

Billion must go first.

Tags:

Swift