Java/kotlin: формат double/int с фиксированным общим количеством цифр

Я пытался искать, но у меня возникла проблема с поиском полного решения этой проблемы: Я хочу отформатировать Int так, чтобы общее количество цифр всегда было 3. Несколько примеров:

1000000 -> 1,00m
678945 -> 678k
65432 -> 65,4k
5437 -> 5,43k

числа никогда не должны быть меньше 1000 или больше 1 миллиарда, поэтому другие случаи не имеют большого значения

это самое близкое, к чему я пришел:

@JvmStatic
        fun formatPointsTop3(points: Int?): String {
            if (points == null) return ""

            val formatter = NumberFormat.getInstance(Locale.ITALIAN)
            val mathContext = MathContext(3, RoundingMode.DOWN)


            return when {
                points < 1000 -> {
                    "$points"
                }
                points < 1000000 -> {
                    val bigDecimal = BigDecimal(points / 1000.0, mathContext)
                    "${formatter.format(bigDecimal)}k"
                }
                else -> {
                    val bigDecimal = BigDecimal(points / 1000000.0, mathContext)
                    "${formatter.format(bigDecimal)}m"
                }
            }
        }

это работает нормально для большинства случаев, за исключением 1000000, которое выводит 1 м (я хочу 1,00 м). Добавление formatter.minimumFractionDigits = 2 добавляет десятичные дроби ко всем числам.

Есть ли способ добиться этого, не делая странных вещей непосредственно на строке?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
269
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Там должен быть. Во-первых, выясните, как вы хотите его отобразить, что, похоже, у вас есть разные взгляды на то, как именно на log (n) (например, на количество цифр во входных данных). Для 7 цифр вы хотите отобразить значение, разделенное на миллион, с 2 дробными цифрами. Для 8 цифр вам нужно значение div миллион с 1 дробью и т. д. Это будет много кода, возможно, манипуляции со строками проще.

Ответ принят как подходящий

В итоге я сделал это:

fun formatPointsTop3(points: Int?): String {
            if (points == null) return ""
            if (points == 0) return "0"

            val maxNumberOfDigits = 3

            val multiplierExponent = log(points.toDouble(), 1000.0).toInt()

            val bigPoints = BigDecimal(points)
            val bigDivider = BigDecimal(1000).pow(multiplierExponent)
            val reducedPoints = bigPoints.divide(bigDivider)

            val intPart = reducedPoints.toBigInteger().toInt()
            val decimalPart = reducedPoints.subtract(BigDecimal(intPart)).toDouble()

            val numberOfDecimals = maxNumberOfDigits - (log10(intPart.toDouble()).toInt() + 1)

            var formattedString = "$intPart"

            if (numberOfDecimals > 0) {
                val multiplier = 10.0.pow(numberOfDecimals)
                val formatter = NumberFormat.getIntegerInstance()
                formatter.minimumIntegerDigits = numberOfDecimals
                formatter.maximumIntegerDigits = numberOfDecimals
                val multiplied = (decimalPart * multiplier).toInt()
                formattedString += ",${formatter.format(multiplied)}"
            }

            formattedString += when (multiplierExponent) {
                0 -> ""
                1 -> "k"
                2 -> "m"
                3 -> "b"
                else -> ""  //this is not possible as max int is 2 billions
            }

            return formattedString
        }

это довольно уродливо, но выглядит лучше, чем манипуляции со строками.

Другие вопросы по теме