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
相关产品推荐
相关产品推荐

