java/kotlin:格式为双精度/int,总位数固定

java/kotlin:格式为双精度/int,总位数固定,java,kotlin,format,bigdecimal,decimalformat,Java,Kotlin,Format,Bigdecimal,Decimalformat,我尝试四处搜索,但在找到此问题的完整解决方案时遇到问题: 我想格式化一个Int,使总位数始终为3。举几个例子: 1000000 -> 1,00m 678945 -> 678k 65432 -> 65,4k 5437 -> 5,43k 数字不应低于1000或大于10亿,因此其他情况并不重要 这是我最接近的一次: @JvmStatic fun formatPointsTop3(points: Int?): String { if (p

我尝试四处搜索,但在找到此问题的完整解决方案时遇到问题: 我想格式化一个
Int
,使总位数始终为3。举几个例子:

1000000 -> 1,00m
678945 -> 678k
65432 -> 65,4k
5437 -> 5,43k
数字不应低于1000或大于10亿,因此其他情况并不重要

这是我最接近的一次:

@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"
                }
            }
        }
@JvmStatic
有趣的格式PointStop3(点:Int?):字符串{
if(points==null)返回“”
val formatter=NumberFormat.getInstance(Locale.意大利语)
val mathContext=mathContext(3,RoundingMode.DOWN)
何时返回{
积分<1000->{
“$points”
}
积分<1000000->{
val bigDecimal=bigDecimal(点数/1000.0,mathContext)
“${formatter.format(bigDecimal)}k”
}
其他->{
val bigDecimal=bigDecimal(点数/1000000.0,mathContext)
“${formatter.format(bigDecimal)}m”
}
}
}
除1000000输出1m(我想要1,00m)外,这在大多数情况下都可以正常工作。添加
formatter.minimumFractionDigits=2
会将小数添加到所有数字中


有没有一种方法可以在不直接对字符串执行奇怪操作的情况下实现这一点?

应该有。首先,弄清楚要如何渲染它,这似乎对每个日志(n)的渲染方式有不同的理解(例如,根据输入中的位数)。对于7位数,您希望渲染值,除以一百万,再加上2个小数位数。对于8位数字,您需要值div million加1个分数,等等。这将需要大量代码,也许字符串操作更简单。

应该有。首先,弄清楚要如何渲染它,这似乎对每个日志(n)的渲染方式有不同的理解(例如,根据输入中的位数)。对于7位数,您希望渲染值,除以一百万,再加上2个小数位数。对于8位数字,您需要值div million加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
        }
这很难看,但它看起来比字符串操作好

我最后做了以下几点:

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
        }
它很难看,但它看起来比字符串操作更好