You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android印尼盾转多币种转换器数字格式问题求助

如何在Kotlin中格式化货币转换结果,避免指数形式并保留最多两位小数?

问题描述

我正在开发一款将印尼盾转换为12种其他货币的货币转换器,以欧元转换为例,期望得到如下格式的结果:

  • 10印尼盾→0.001欧元
  • 100印尼盾→0.006欧元
  • 1000印尼盾→0.06欧元
  • 100,000印尼盾→6欧元
  • 1,000,000印尼盾→60欧元
  • 10,000,000印尼盾→600欧元

我设置了输入字段,输入值后其他结果会自动更新,但当前显示结果会出现指数形式,希望将结果格式化为最多保留两位小数。附我的Kotlin代码如下:

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        valeurIdr.addTextChangedListener(object : TextWatcher {
            override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
                if (s.toString().equals("")) {
                    resultEuro.text=null
                } else {
                    val idr = valeurIdr?.text.toString().toDouble()
                    val euro = 0.000060
                    resultEuro?.setText((idr * euro).toString())
                }
            }
            override fun beforeTextChanged(
                s: CharSequence, start: Int, count: Int, after: Int) {
            }
            override fun afterTextChanged(s: Editable) {
                // TODO Auto-generated method stub
            }
        })
    }
}

解决方案

问题出在直接调用Double.toString()上——当数值非常小的时候,Kotlin会默认用科学计数法(指数形式)来显示结果。我们可以用DecimalFormat类来精确控制输出格式,确保结果以普通小数形式展示,并且最多保留两位小数。

修改后的代码

import java.text.DecimalFormat

class MainActivity : AppCompatActivity() {
    // 初始化DecimalFormat,模式"0.##"表示最多保留两位小数,无多余末尾零
    private val decimalFormat = DecimalFormat("0.##")

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        valeurIdr.addTextChangedListener(object : TextWatcher {
            override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
                if (s.toString().trim().isEmpty()) {
                    resultEuro.text = null
                } else {
                    try {
                        val idr = s.toString().toDouble()
                        val euroRate = 0.000060
                        val euroAmount = idr * euroRate
                        // 用DecimalFormat格式化结果,避免指数形式
                        resultEuro?.text = decimalFormat.format(euroAmount)
                    } catch (e: NumberFormatException) {
                        // 处理输入非数字的情况,比如输入字母或特殊字符
                        resultEuro?.text = "无效输入"
                    }
                }
            }

            override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}

            override fun afterTextChanged(s: Editable) {}
        })
    }
}

关键说明

  1. DecimalFormat模式"0.##"的含义是:

    • 0:强制显示整数部分,即使是0也会显示
    • ##:最多显示两位小数,只有当小数部分有值时才会显示,不会出现末尾多余的零(比如结果是6.0的话,会显示为6而不是6.00
      如果你希望强制保留两位小数(比如6显示为6.00),可以把模式改成"0.00"
  2. 异常处理:添加了NumberFormatException的捕获,防止用户输入非数字内容导致崩溃,提升应用稳定性。

  3. 避免科学计数法DecimalFormat默认不会使用科学计数法来展示常规范围内的数值,完美解决你遇到的指数形式问题。

替代方案(本地化适配)

如果你的应用需要适配不同地区的数字格式(比如有的地区用逗号做小数分隔符),可以用NumberFormat来实现:

private val numberFormat = NumberFormat.getInstance().apply {
    maximumFractionDigits = 2
    minimumFractionDigits = 0
    isGroupingUsed = false // 不需要千位分隔符的话设置为false
}

然后用numberFormat.format(euroAmount)来格式化结果即可。


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

火山引擎 最新活动