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, my 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()
}
}
CodePudding user response:
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.
CodePudding user response:
import java.math.BigDecimal
import java.math.RoundingMode.HALF_EVEN
fun roundBigNumber(number: Long): String {
fun calc(divisor: Long) = BigDecimal(number.toDouble() / divisor)
.setScale(2, HALF_EVEN)
.toString()
.dropLastWhile { it == '0' }
.dropLastWhile { it == '.' }
return when {
number in 1000..999994 -> calc(1000) "k"
number in 999995..999999 -> "999.99k"
number in 1000000..999994999 -> calc(1000000) "m"
number in 999995000..999999999 -> "999.99m"
number in 1000000000..999994999999 -> calc(1000000000) "b"
number in 999995000000..999999999999 -> "999.99b"
number in 1000000000000..999994999999999 -> calc(1000000000000) "t"
number in 999995000000000..999999999999999 -> "999.99t"
number >= 1000000000000000 -> "∞"
else -> number.toString()
}
}