import java.math.RoundingMode
import java.text.DecimalFormat
object Arithmometer {
const val REGEX_VALID = "^[-+×÷*/()\\d.]*$" // 有效式子
const val REGEX_NUM = "(?<!(\\d|\\)))-?(\\d+\\.?\\d*|\\.\\d+)" // 数字 - 前方不是数字或右括弧:负号(非减号) 数字[.数字] 或者 .数字
const val REGEX_SINGLE = "($REGEX_NUM)([-+×÷*/])($REGEX_NUM)" // 单运算符式子
const val REGEX_ADD_SUB = "($REGEX_NUM)([-+])($REGEX_NUM)" // 单运算符式子 - 加减
const val REGEX_MUL_DIV = "($REGEX_NUM)([×÷*/])($REGEX_NUM)" // 单运算符式子 - 乘除
const val REGEX_BRACKET = "\\([-+×÷*/\\d.]*\\)" // 括号式子
const val REGEX_DOUBLE_MINUS = "(?<!(\\d|\\)))--" // 负负(得正)
@Throws(IllegalStateException::class)
fun compute(formula: String): String {
return "\\s".toRegex().replace(formula, "").also {
if (!REGEX_VALID.toRegex().matches(it)) error("syntax error")
}.run {
val cl = count { it == '(' }
val cr = count { it == ')' }
if (cl > cr) {
(0 until cl - cr).joinToString("") { ")" }.let { "$this$it" }
} else if (cr > cl) {
if (takeLast(cr - cl).any { it == ')' }) {
dropLast(cr - cl)
} else error("syntax error")
} else this
}.analyze()
}
private fun String.analyze(): String {
var str = this.also { println(">$it") }
// 括号优先
var pattern = REGEX_BRACKET.toPattern()
var matcher = pattern.matcher(str)
while (matcher.find()) {
str = str.replaceRange(matcher.start() until matcher.end(),
matcher.group().run { substring(1..length - 2) }.analyze()).also { println("=$it") }
matcher = pattern.matcher(str)
}
// 负负得正
if ("--" in str) {
str = REGEX_DOUBLE_MINUS.toRegex().replace(str, "").also { println("=$it") }
}
// 先×÷再+-
for (regexOp in arrayOf(REGEX_MUL_DIV, REGEX_ADD_SUB)) {
pattern = regexOp.toPattern()
matcher = pattern.matcher(str)
while (matcher.find()) {
val sub = matcher.group()
str = str.replaceRange(matcher.start() until matcher.end(), sub.operate()).also { println("=$it") }
matcher = pattern.matcher(str)
}
}
return str
}
private fun String.operate(): String {
return REGEX_SINGLE.toRegex()
.replace(this, "$1`$4`$5")
.split('`')
.takeIf { it.size == 3 }
?.let { Triple(it[0].toBigDecimal(), it[1][0], it[2].toBigDecimal()) }
?.run {
when (second) {
'+' -> first.add(third).toString()
'-' -> first.subtract(third).toString()
'×', '*' -> first.multiply(third).toString()
'÷', '/' -> first.divide(third, 10, RoundingMode.HALF_UP)
.let { DecimalFormat("##0.##########").format(it) }
else -> error("syntax error")
}/*.also { println(">$formula=$it") }*/
} ?: error(this)
}
}
网友评论