如何从多项式字符串中提取系数?技术实现求助
提取多项式系数的可靠实现方案
我之前也踩过用split处理多项式系数的坑——这种分割方式很难覆盖x一次项、常数项、缺项这些边界情况,用正则表达式匹配每一项再逐个解析会靠谱很多。下面给你梳理完整的实现思路和代码:
核心难点梳理
要解决这个问题,得覆盖所有可能的项格式:
- 高次项:比如
7x^4、-3x^3 - 一次项:
x(系数为1)、-x(系数为-1)、2x - 常数项:
5、-8 - 缺项:多项式里未出现的次数,对应系数要填0
解决方案:正则匹配+逐项解析
步骤1:用正则捕获所有项的关键信息
我们可以写一个正则表达式,一次性匹配出每个项的符号、系数、次数:
val termRegex = Regex("([+-]?)(\\d*)(x(?:\\^(\\d+))?)?")
这个正则的分组含义:
- 第1组:项的符号(
+/-,第一个项可能没有,默认是+) - 第2组:系数的数字部分(可能为空,比如
x的系数就是1) - 第3组:x相关部分(可能是
x、x^n或者空) - 第4组:次数数字(只有
x^n时存在,x的话次数是1,常数项次数是0)
步骤2:预处理输入字符串
为了统一处理第一个项没有符号的情况(比如7x^4),给字符串开头补一个+:
val processedText = if (text.first() in setOf('+', '-')) text else "+$text"
步骤3:解析每一项,记录系数和次数
遍历所有匹配到的项,解析出每个项的系数和对应次数,同时记录最高次数:
val terms = termRegex.findAll(processedText) val coefficientMap = mutableMapOf<Int, Int>() var maxDegree = 0 for (term in terms) { val sign = if (term.groupValues[1] == "-") -1 else 1 val coeffStr = term.groupValues[2] val xPart = term.groupValues[3] val degreeStr = term.groupValues[4] // 处理系数 val coeff = when { coeffStr.isEmpty() && xPart.isNotEmpty() -> sign * 1 // 处理x/-x的情况 coeffStr.isEmpty() && xPart.isEmpty() -> 0 // 空项,直接跳过 else -> sign * coeffStr.toInt() } // 处理次数 val degree = when { xPart.isEmpty() -> 0 // 常数项 degreeStr.isEmpty() -> 1 // 一次项x else -> degreeStr.toInt() } if (coeff != 0) { // 忽略系数为0的无效项 coefficientMap[degree] = coeff if (degree > maxDegree) maxDegree = degree } }
步骤4:填充缺项,生成最终系数列表
从最高次数到0次依次取出系数,缺项的位置自动填充0:
val koefList = mutableListOf<Int>() for (degree in maxDegree downTo 0) { koefList.add(coefficientMap.getOrDefault(degree, 0)) }
完整的Kotlin函数
把上面的步骤整合起来,完整函数如下:
private fun koef(text: String): List<Int> { if (text.isEmpty()) return emptyList() // 预处理:给开头补符号(如果没有的话) val processedText = if (text.first() in setOf('+', '-')) text else "+$text" val termRegex = Regex("([+-]?)(\\d*)(x(?:\\^(\\d+))?)?") val coefficientMap = mutableMapOf<Int, Int>() var maxDegree = 0 termRegex.findAll(processedText).forEach { match -> val sign = if (match.groupValues[1] == "-") -1 else 1 val coeffStr = match.groupValues[2] val xPart = match.groupValues[3] val degreeStr = match.groupValues[4] val coeff = when { coeffStr.isEmpty() && xPart.isNotEmpty() -> sign * 1 coeffStr.isEmpty() && xPart.isEmpty() -> 0 // 空项,忽略 else -> sign * coeffStr.toInt() } val degree = when { xPart.isEmpty() -> 0 degreeStr.isEmpty() -> 1 else -> degreeStr.toInt() } if (coeff != 0) { coefficientMap[degree] = coeff if (degree > maxDegree) maxDegree = degree } } // 生成从最高次到0次的系数列表,缺项填0 return (maxDegree downTo 0).map { coefficientMap.getOrDefault(it, 0) } }
测试示例
- 输入
"7x^4+3x^3-6x^2+x-8",返回[7, 3, -6, 1, -8](对应x⁴到常数项的系数) - 输入
"x^3-5",返回[1, 0, 0, -5](自动补全x²和x项的0系数)
为什么原有方法容易出问题?
split分割的方式无法统一处理所有边界情况:比如x项没有^、开头无符号、常数项和x项混合的场景,而正则可以一次性捕获每个项的所有关键信息,解析逻辑会清晰很多。
内容的提问来源于stack exchange,提问作者Marlock
相关产品推荐
相关产品推荐

