Search code examples
androidkotlinnumbers

How do you remove extra zeros at the end of a decimal in Kotlin?


I'm creating a function that rounds large numbers over 1,000 and then returns a string of that rounded number. For example, "2374293" would return as "2.37m"
However, I dont want any extra zeros at the end of decimals like "25.00" or "100.50".

For Example:

What I want:

 Input  ->  Output

"11000" -> "11k"
"11400" -> "11.4k"

What I get:

 Input  ->  Output

"11000" -> "11.00k"
"11400" -> "11.40k"

How would I remove these zeros and decimal point(if it's a whole number) when needed?

Here is my code currently:

    private fun roundBigNumb(numb: Long): String {
    val newNumb = numb.toDouble()
    return when {
        numb in 1000..999994 -> {
            BigDecimal(newNumb/1000).setScale(2, RoundingMode.HALF_EVEN).toString()+"k"
        }
        numb in 999995..999999 -> {
            "999.99k"
        }
        numb in 1000000..999994999 -> {
            BigDecimal(newNumb/1000000).setScale(2, RoundingMode.HALF_EVEN).toString()+"m"
        }

        numb in 999995000..999999999 -> {
            "999.99m"
        }

        numb in 1000000000..999994999999 -> {
            BigDecimal(newNumb/1000000000).setScale(2, RoundingMode.HALF_EVEN).toString()+"b"
        }

        numb in 999995000000..999999999999 -> {                    
            "999.99b"
        }

        numb in 1000000000000..999994999999999 -> {
            BigDecimal(newNumb/1000000000000).setScale(2, RoundingMode.HALF_EVEN).toString()+"t"
        }

        numb in 999995000000000..999999999999999 -> {
            "999.99t"
        }

        numb >= 1000000000000000 -> "∞"

        else -> numb.toString()
    }
}

Solution

  • Once you have converted the number to a string with up to 2 decimal places (as you are doing), you can use dropLastWhile to drop trailing zeros and decimal places.

    Here is an example

    fun prettyFormat(input: Double): String {
        if( input == 0.0 ) return "0"
        
        val prefix = if( input < 0 ) "-" else ""
        val num = abs(input)
    
        // figure out what group of suffixes we are in and scale the number
        val pow = floor(log10(num)/3).roundToInt()
        val base = num / 10.0.pow(pow * 3)
    
        // Using consistent rounding behavior, always rounding down since you want
        // 999999999 to show as 999.99M and not 1B
        val roundedDown = floor(base*100)/100.0
    
        // Convert the number to a string with up to 2 decimal places
        var baseStr = BigDecimal(roundedDown).setScale(2, RoundingMode.HALF_EVEN).toString()
    
        // Drop trailing zeros, then drop any trailing '.' if present
        baseStr = baseStr.dropLastWhile { it == '0' }.dropLastWhile { it == '.' }
    
        val suffixes = listOf("","k","M","B","T")
    
        return when {
            pow < suffixes.size -> "$prefix$baseStr${suffixes[pow]}"
            else -> "${prefix}infty"
        }
    }
    

    This produces

    11411.0   = 11.41k
    11000.0   = 11k
    9.99996E8 = 999.99M
    12.4      = 12.4
    0.0       = 0
    -11400.0  = -11.4k
    

    If you don't care about zero or negative numbers it can be simplified a bit.