Kotlin中如何生成带货币符号而非货币代码的价格字符串?
问题分析
你的代码当前输出SGD 5.00而非预期的$5.00,核心原因是NumberFormat.getCurrencyInstance()默认使用JVM的默认Locale,当该Locale与传入的货币代码不匹配时,会优先显示货币代码而非本地化符号。而替换为Locale.getDefault()后出现英镑符号,说明你的设备/JVM默认Locale被设置为英国地区(en_GB),和实际所在的新加坡地区不匹配。
解决方案
要正确显示对应货币的本地化符号,需要根据货币代码匹配对应的Locale,再用该Locale创建货币格式化器。
方法1:通用匹配(遍历系统可用Locale)
通过遍历系统所有可用Locale,找到与目标货币代码匹配的Locale,确保格式化器遵循正确的地区显示规则:
fun getLocaleForCurrency(currencyCode: String): Locale { return Locale.getAvailableLocales() .firstOrNull { locale -> try { Currency.getInstance(locale).currencyCode == currencyCode } catch (e: IllegalArgumentException) { false } } ?: Locale.getDefault() } fun getMonthlyPriceString(yearlyPriceMicros: Long, currencyCode: String): String { val targetLocale = getLocaleForCurrency(currencyCode) val format = NumberFormat.getCurrencyInstance(targetLocale) format.maximumFractionDigits = 2 // 使用Double避免Float精度丢失,高精度场景建议用BigDecimal val monthlyPrice = yearlyPriceMicros.toDouble() / 1_000_000.0 / 12.0 return format.format(monthlyPrice) }
方法2:手动映射常用货币(更高效)
如果业务仅涉及有限的常用货币,可以直接创建货币代码与对应Locale的映射表,避免遍历系统Locale的开销:
private val CURRENCY_LOCALE_MAP = mapOf( "SGD" to Locale("en", "SG"), "USD" to Locale("en", "US"), "EUR" to Locale("fr", "FR"), "GBP" to Locale("en", "GB") ) fun getMonthlyPriceString(yearlyPriceMicros: Long, currencyCode: String): String { val targetLocale = CURRENCY_LOCALE_MAP[currencyCode] ?: Locale.getDefault() val format = NumberFormat.getCurrencyInstance(targetLocale) format.maximumFractionDigits = 2 val monthlyPrice = yearlyPriceMicros.toDouble() / 1_000_000.0 / 12.0 return format.format(monthlyPrice) }
关键说明
- 用对应货币的Locale创建
NumberFormat后,无需手动设置format.currency,因为Locale已经关联了正确的货币显示规则。 - 金额计算优先使用
Double或BigDecimal,避免Float的精度丢失问题(大额金额计算时误差会被放大)。
内容的提问来源于stack exchange,提问作者Wilfred
相关产品推荐
相关产品推荐

