Kotlin 数值解析器无法处理“10”,并在与 10 相乘时给出 E+

Kotlin numerical parser cannot work with `10` and gives E+ when multiplying with 10

预期输出:3650
我已经用许多数值表达式测试了我的代码,都给出了正确的答案。 只有 10 个造成了所有问题

我的MParser.kt文件

package com.parser

import java.math.BigDecimal
import java.math.RoundingMode

class MParser(private var mainExp: String) {
    var originalExp: String = ""
    init {
        println(mainExp)
        mainExp = mainExp.dePrettify()
        originalExp = mainExp
    }

    fun calc(): String {
        calcD()
        calcM()
        rearrange()
        calcA()
        calcMi()
        if (mainExp==originalExp)
            return "Hello"
        return mainExp
    }

    private fun dividable(): MutableList<String> {
        val divisible = mutableListOf<String>()
        Regex("(\d+\.*\d*)(/+(\d+\.*\d*))+").apply {
            this.findAll(mainExp).toMutableList().forEach {
                divisible.add(it.value)
            }
        }
        return divisible
    }

    private fun calcD() {
        dividable().forEach {
            mainExp = mainExp.replace(it, divide(it).toString())
        }
    }


    private fun divide(exp: String): BigDecimal {
        val num = toDoubleMutableList(exp.split("/").toMutableList())
        while (num.size > 1) {
            val dividend = num[0]
            val divisor = num[1]
            val quotient = dividend.divide(divisor, 3, RoundingMode.HALF_UP)
            num[0] = quotient
            num.removeAt(1)
        }
        return num[0]
    }

    private fun multiplies(): MutableList<String> {
        val multiplies = mutableListOf<String>()
        Regex("(\d+\.*\d*)(\*+(\d+\.*\d*))+").apply {
            this.findAll(mainExp).toMutableList().forEach {
                multiplies.add(it.value)
            }
        }
        return multiplies
    }

    private fun calcM() {
        multiplies().forEach {
            mainExp = mainExp.replace(it, multiply(it).toString())
        }
    }

    private fun multiply(exp: String): BigDecimal {
        val num = toDoubleMutableList(exp.split("*").toMutableList())
        while (num.size > 1) {
            val factor1 = num[0]
            val factor2 = num[1]
            val product = factor1 * factor2
            num[0] = product
            num.removeAt(1)
        }
        return num[0]
    }


    private fun addable(): MutableList<String> {
        // 5*9*69/3/99+45-78*6/3/2-89 = sample
        val multiplies = mutableListOf<String>()
        Regex("(\d+\.*\d*)(\++(\d+\.*\d*))+").apply {
            this.findAll(mainExp).toMutableList().forEach {
                multiplies.add(it.value)
            }
        }
        return multiplies
    }

    private fun calcA() {
        addable().forEach {
            mainExp = mainExp.replace(it, add(it).toString())
        }
    }

    private fun add(exp: String): BigDecimal {
        val num = toDoubleMutableList(exp.split("+").toMutableList())
        while (num.size > 1) {
            val addend1 = num[0]
            val addend2 = num[1]
            val sum = addend1 + addend2
            num[0] = sum
            num.removeAt(1)
        }
        return num[0]
    }

    private fun minusable(): MutableList<String> {
        // 5*9*69/3/99+45-78*6/3/2-89 = sample
        val multiplies = mutableListOf<String>()
        Regex("(\d+\.*\d*)(-+(\d+\.*\d*))+").apply {
            this.findAll(mainExp).toMutableList().forEach {
                multiplies.add(it.value)
            }
        }
        return multiplies
    }

    private fun calcMi() {
        minusable().forEach {
            mainExp = mainExp.replace(it, minus(it).toString())
        }
    }

    fun minus(exp: String): BigDecimal {
        val num = toDoubleMutableList(exp.split("-").toMutableList())
        while (num.size > 1) {
            val addend1 = num[0]
            val addend2 = num[1]
            val sum = addend1 - addend2
            num[0] = sum
            num.removeAt(1)
        }
        return num[0]
    }

    /*
    Utility -- Methods
     */

    private fun rearrange() {
        val subtracts = mutableListOf<String>()
        Regex("(-(\d+\.*\d*))").apply {
            this.findAll(mainExp).forEach {
                subtracts.add(it.value)
            }
        }
        subtracts.forEach {
            mainExp = mainExp.replaceFirst(it, "")
            mainExp += it
        }
        if (mainExp.startsWith("+"))
            mainExp = mainExp.replaceFirst("+", "")
    }

    fun isParenthesisValid(): Boolean {
        var valid = true
        val stack = ArrayDeque<Char>()

        for (symb in mainExp) {
            if (symb == '(' || symb == '[' || symb == '{')
                stack.addLast(symb)
            else if (symb == ')' || symb == ']' || symb == '}') {
                if (stack.isEmpty())
                    valid = false
                else {
                    val i = stack.removeLast()
                    if (i == '(' && symb != ')' || i == '{' && symb != '}' || i == '[' && symb != ']')
                        valid = false
                } //end else
            }
            println("stack: $stack")
        } //end for-loop
        if (stack.isNotEmpty())
            valid = false
        return valid
    }

    private fun String.dePrettify(): String {
        return this.replace(" ", "").replace("÷", "/").replace("×", "*")
    }

    fun optimize(exp: String): String {
        return exp.replace(" ", "").replace("÷", "/").replace("×", "*")
    }
}

fun toDoubleMutableList(list: MutableList<String>): MutableList<BigDecimal> {
    val tempList = mutableListOf<BigDecimal>()
    for (i in list) {
        val b = BigDecimal(i.toDouble().toString()).stripTrailingZeros()
        tempList.add(b)
    }
    return tempList
}

当我在另一个 .kt file 中执行 val value = try {MParser("365*10").calc()} catch (e: NumberFormatException) {"Error"} 时,我得到 value = 3.65E+3
E+是怎么出现的?


我调试了代码。

我认为问题是从calcMi()开始的。检查一次,因为我不明白该怎么做。

我测试过并正确的表达式:

    //whole numbers
    val wexp0 = "12 + 4 - 8 ÷ 2 × 3".optimize() //4
    val wexp1 = "7 - 5 + 14 ÷ 2 + 6".optimize() //15
    val wexp2 = "37 - 6 × 4 + 32 ÷ 8".optimize() //17
    val wexp3 = "64 - 48 ÷ 6 × 4 + 8".optimize() //40

    //decimal numbers
    val dexp0 = "5*9*69/3/99+45-78*6/3/2-89-4/5+62.2/2/4"
    val dexp1 = "-5+4-4+1-78+86-21+9+5-5-1+9.787-2+1000"
    val dexp2 = "0.2 + 1.3 - 0.4 × 1.5".optimize() //0.9
    val dexp3 = "0.3 × 0.4 - 2.4 ÷ 6 + 1.2 × 4".optimize() //4.52
    val dexp4 = "0.72 ÷ 1.2 + 3.5 × 4.2 - 1.6".optimize() //13.7
    val dexp5 = "9.2 + 3.5 - 4.9 - 3.5 ÷ 0.7 × 1.2".optimize() //1.8
    val dexp6 = "95.01 × 1.2 - 2.4 ÷ 2".optimize() //4.812

但是正如你所看到的,我在上面的任何一个中都没有使用过 10。当我使用 10 时,我突然发现了问题。

请仔细查看调试图像。 10 甚至在乘法完成之前就被转换为 1E+1

终于解决了问题

我已经将 minus()add()multiply()divide() 的所有 return 类型更改为 string 而不是保留它 BigDecimal


这些方法中的每一个都是 returning BigDecimal,因此我在输出中得到了 E+。但是我观察到这些方法的所有 returned 值最终都添加到 String

所以在计算之后,我将 toPlainString() 应用于 returned 的 BigDecimal

通过这样做,E+ 不会出现在输出中,我也不必一一管理尾随零。

新密码

package com.parser

import java.math.BigDecimal
import java.math.RoundingMode

class MParser(private var mainExp: String) {
    var originalExp: String = ""
    init {
        println(mainExp)
        mainExp = mainExp.dePrettify()
        originalExp = mainExp
    }

    fun calc(): String {
        calcD()
        calcM()
        rearrange()
        calcA()
        calcMi()
        if (mainExp==originalExp)
            return "Hello"
        return mainExp
    }

    private fun dividable(): MutableList<String> {
        val divisible = mutableListOf<String>()
        Regex("(\d+\.*\d*)(/+(\d+\.*\d*))+").apply {
            this.findAll(mainExp).toMutableList().forEach {
                divisible.add(it.value)
            }
        }
        return divisible
    }

    private fun calcD() {
        dividable().forEach {
            mainExp = mainExp.replace(it, divide(it).toString())
        }
    }


    private fun divide(exp: String): String {
        val num = toDoubleMutableList(exp.split("/").toMutableList())
        while (num.size > 1) {
            val dividend = num[0]
            val divisor = num[1]
            val quotient = dividend.divide(divisor, 3, RoundingMode.HALF_UP)
            num[0] = quotient
            num.removeAt(1)
        }
        return num[0].toPlainString()
    }

    private fun multiplies(): MutableList<String> {
        val multiplies = mutableListOf<String>()
        Regex("(\d+\.*\d*)(\*+(\d+\.*\d*))+").apply {
            this.findAll(mainExp).toMutableList().forEach {
                multiplies.add(it.value)
            }
        }
        return multiplies
    }

    private fun calcM() {
        multiplies().forEach {
            mainExp = mainExp.replace(it, multiply(it).toString())
        }
    }

    private fun multiply(exp: String): String {
        val num = toDoubleMutableList(exp.split("*").toMutableList())
        while (num.size > 1) {
            val factor1 = num[0]
            val factor2 = num[1]
            val product = factor1 * factor2
            num[0] = product.stripTrailingZeros()
            num.removeAt(1)
        }
        return num[0].toPlainString()
    }


    private fun addable(): MutableList<String> {
        // 5*9*69/3/99+45-78*6/3/2-89 = sample
        val multiplies = mutableListOf<String>()
        Regex("(\d+\.*\d*)(\++(\d+\.*\d*))+").apply {
            this.findAll(mainExp).toMutableList().forEach {
                multiplies.add(it.value)
            }
        }
        return multiplies
    }

    private fun calcA() {
        addable().forEach {
            mainExp = mainExp.replace(it, add(it).toString())
        }
    }

    private fun add(exp: String): String {
        val num = toDoubleMutableList(exp.split("+").toMutableList())
        while (num.size > 1) {
            val addend1 = num[0]
            val addend2 = num[1]
            val sum = addend1 + addend2
            num[0] = sum
            num.removeAt(1)
        }
        return num[0].toPlainString()
    }

    private fun minusable(): MutableList<String> {
        // 5*9*69/3/99+45-78*6/3/2-89 = sample
        val multiplies = mutableListOf<String>()
        Regex("(\d+\.*\d*)(-+(\d+\.*\d*))+").apply {
            this.findAll(mainExp).toMutableList().forEach {
                multiplies.add(it.value)
            }
        }
        return multiplies
    }

    private fun calcMi() {
        minusable().forEach {
            mainExp = mainExp.replace(it, minus(it).toString())
        }
    }

    fun minus(exp: String): String {
        val num = toDoubleMutableList(exp.split("-").toMutableList())
        while (num.size > 1) {
            val addend1 = num[0]
            val addend2 = num[1]
            val sum = addend1 - addend2
            num[0] = sum
            num.removeAt(1)
        }
        return num[0].toPlainString()
    }

    /*
    Utility -- Methods
     */

    private fun rearrange() {
        val subtracts = mutableListOf<String>()
        Regex("(-(\d+\.*\d*))").apply {
            this.findAll(mainExp).forEach {
                subtracts.add(it.value)
            }
        }
        subtracts.forEach {
            mainExp = mainExp.replaceFirst(it, "")
            mainExp += it
        }
        if (mainExp.startsWith("+"))
            mainExp = mainExp.replaceFirst("+", "")
    }

    fun isParenthesisValid(): Boolean {
        var valid = true
        val stack = ArrayDeque<Char>()

        for (symb in mainExp) {
            if (symb == '(' || symb == '[' || symb == '{')
                stack.addLast(symb)
            else if (symb == ')' || symb == ']' || symb == '}') {
                if (stack.isEmpty())
                    valid = false
                else {
                    val i = stack.removeLast()
                    if (i == '(' && symb != ')' || i == '{' && symb != '}' || i == '[' && symb != ']')
                        valid = false
                } //end else
            }
            println("stack: $stack")
        } //end for-loop
        if (stack.isNotEmpty())
            valid = false
        return valid
    }

    private fun String.dePrettify(): String {
        return this.replace(" ", "").replace("÷", "/").replace("×", "*")
    }

    fun optimize(exp: String): String {
        return exp.replace(" ", "").replace("÷", "/").replace("×", "*")
    }
}

fun toDoubleMutableList(list: MutableList<String>): MutableList<BigDecimal> {
    val tempList = mutableListOf<BigDecimal>()
    for (i in list) {
        val b = BigDecimal(i).stripTrailingZeros()
        tempList.add(b)
    }
    return tempList
}