You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android应用DecimalFormat引发NumberFormatException(逗号输入串)

解决Kotlin中DecimalFormat导致的NumberFormatException(南非区域设备)

原因分析

问题核心是区域设置(Locale)差异:

  • DecimalFormat 默认会使用设备的系统区域设置来格式化数字。南非部分地区(如南非英语、南非荷兰语区域)的小数分隔符是逗号(,)而非常见的点(.),因此调用 df.format(number) 时,输出的字符串会是类似 "0,3" 的格式。
  • 而 String.toFloat()(底层依赖Java的Float.parseFloat)遵循Locale.US的解析规则,仅识别点作为小数分隔符,遇到逗号时就会抛出NumberFormatException。
  • 你提到参数是Float类型没问题,这点完全正确——错误并非输入参数导致,而是格式化后的字符串解析环节因区域设置不匹配出现了问题。

解决方法

方法1:指定DecimalFormat使用固定Locale

强制DecimalFormat使用不会产生逗号分隔符的Locale(如Locale.US或Locale.ROOT),确保格式化输出的字符串始终用点作为小数分隔符:

fun roundOffDecimal(number: Float): Float {
    // 指定Locale.US,强制小数分隔符为点
    val df = DecimalFormat("#.#", DecimalFormatSymbols(Locale.US))
    df.roundingMode = RoundingMode.FLOOR
    return df.format(number).toFloat()
}

方法2:用对应Locale的NumberFormat解析字符串

如果需要保留系统区域的格式化逻辑,解析时也要用相同Locale的NumberFormat处理,而非直接调用toFloat():

fun roundOffDecimal(number: Float): Float {
    val df = DecimalFormat("#.#")
    df.roundingMode = RoundingMode.FLOOR
    val formattedStr = df.format(number)
    // 使用和格式化相同的Locale来解析字符串
    return df.parse(formattedStr).toFloat()
}

方法3:直接用数学运算替代字符串格式化

最稳妥的方式是绕开字符串转换环节,直接用数学方法实现向下取整保留一位小数,彻底避免区域相关问题:

fun roundOffDecimal(number: Float): Float {
    return Math.floor(number * 10) / 10.0f
}

该逻辑通过将数字乘以10后向下取整,再除以10,实现和原代码完全一致的效果,且无任何区域依赖。

内容的提问来源于stack exchange,提问作者Shashank Pednekar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 02:57:34