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

Android计算器解析器处理负数时触发NumberFormatException问题求助

Android计算器解析器负数处理修复方案

问题根源

原解析器核心问题是无法区分一元负号(表示负数)和二元减号(减法运算):

  • 输入-5+5时,直接用运算符分割会得到["", "5", "5"],空字符串调用toFloat()触发NumberFormatException。
  • getDelimiter方法逻辑错误,遇到+返回空字符串,且无法正确识别表达式中的有效二元运算符。

修复方案

以下是修改后的完整代码,重点调整字符串分割逻辑、运算符识别逻辑,保留原有计算逻辑:

class CalculatorParser(private var expression: String) {

    init {
        if (expression.isEmpty() || expression == "0") {
            expression = "0+0"
        } else if (!expression.contains(Regex("[+\\-*/^]"))) {
            // 仅当表达式无任何运算符时,才追加+0
            expression = "$expression+0"
        }
    }

    // 使用正则分割:区分一元负号和二元运算符
    private val splitStr: MutableList<String> = run {
        // 正则规则:在+/*^后分割,或在非运算符位置前遇到-时不分割(保留负数)
        val regex = Regex("(?<=[+*/^])|(?=-)(?![+*/^])")
        val parts = expression.split(regex).filter { it.isNotEmpty() }.toMutableList()
        // 处理开头就是负数的情况,确保分割后有至少两个元素
        if (parts.size == 1) {
            parts.add("0")
        }
        parts
    }

    private val a = splitStr[0].toFloat()
    private val b = splitStr[1].toFloat()
    private val operator = getDelimiter(expression)

    private fun getDelimiter(str: String): String {
        // 优先匹配二元运算符,排除开头的一元负号
        return when {
            str.contains("+") -> "+"
            str.substring(1).contains("-") -> "-" // 从索引1开始检查,跳过开头的负号
            str.contains("*") -> "*"
            str.contains("^") -> "^"
            str.contains("/") -> "/"
            else -> "+"
        }
    }

    private fun calculate(): Float {
        return when (operator) {
            "+" -> a + b
            "-" -> a - b
            "*" -> a * b
            "/" -> a / b
            "^" -> pow(a.toInt(), b.toInt()).toFloat()
            else -> 0f
        }
    }

    fun eval(result: Float = calculate()): String {
        return if (result.toString().contains(".")) {
            val splitResult = result.toString().split(".")
            if (splitResult[1].toInt() > 0) {
                result.toString()
            } else {
                result.toInt().toString()
            }
        } else {
            result.toString()
        }
    }

    private fun pow(base: Int, power: Int): Int {
        var result = base
        var i = 1
        while (i < power) {
            result *= base
            i++
        }
        return result
    }
}

关键修改说明

  1. 正则分割逻辑:使用(?<=[+*/^])|(?=-)(?![+*/^])正则表达式,确保仅在二元运算符后分割,保留负数的一元负号。
  2. 运算符识别优化:getDelimiter从索引1开始检查-,避免把开头的负号误判为减法运算符。
  3. 初始化逻辑调整:用正则判断表达式是否含运算符,替代原有的split长度判断,准确性更高。

测试验证

输入-5+5时:

  • splitStr结果为["-5", "5"]
  • 识别运算符为+
  • 计算结果-5 + 5 = 0,符合预期

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 19:27:23