Swift化学式解析问题:带括号的摩尔质量计算结果异常
括号处理逻辑错误的修复方案:化合物摩尔质量计算
你的代码核心问题是处理括号后的乘数时,错误地将整个累计的总质量(包括括号外的元素)乘以了倍数。比如计算Mg(NO3)2时,代码会先累加Mg的质量,再累加N和3个O的质量得到totalMass = Mg + N + 3O,然后乘以2,最终得到(Mg + N + 3O)*2,而正确结果应该是Mg + (N + 3O)*2。
修复思路
- 遇到左括号时,把当前的总质量存入栈中,然后重置当前总质量为0,专门计算括号内元素的总质量。
- 处理完右括号和对应的乘数后,将括号内的总质量乘以乘数,再加上栈中取出的括号前的总质量,作为新的总质量。
修改后的完整代码
func calculateMolarMass() { var totalMass = 0.0 var i = compoundFormula.startIndex var massStack: [Double] = [] var operatorStack: [Character] = [] var openParenthesesCount = 0 var openSquareBracketsCount = 0 while i < compoundFormula.endIndex { let char = compoundFormula[i] if char.isLetter { var elementSymbol = String(char) i = compoundFormula.index(after: i) while i < compoundFormula.endIndex && compoundFormula[i].isLowercase { elementSymbol.append(compoundFormula[i]) i = compoundFormula.index(after: i) } var subscriptValue = "" while i < compoundFormula.endIndex && compoundFormula[i].isNumber { subscriptValue.append(compoundFormula[i]) i = compoundFormula.index(after: i) } let elementMass = atomicMasses[elementSymbol] ?? 0.0 let multiplier = Double(subscriptValue) ?? 1.0 totalMass += elementMass * multiplier } else if char == "(" || char == "[" { // 保存括号前的总质量,重置当前总质量计算括号内部分 massStack.append(totalMass) totalMass = 0.0 operatorStack.append(char) i = compoundFormula.index(after: i) if char == "(" { openParenthesesCount += 1 } else { openSquareBracketsCount += 1 } } else if char == ")" || char == "]" { let openBracket: Character = char == ")" ? "(" : "[" i = compoundFormula.index(after: i) while !operatorStack.isEmpty && operatorStack.last != openBracket { applyOperator(&totalMass, &massStack, operatorStack.removeLast()) } if operatorStack.isEmpty || operatorStack.last != openBracket { fatalError("括号不匹配") } if char == ")" { openParenthesesCount -= 1 } else { openSquareBracketsCount -= 1 } operatorStack.removeLast() // 移除左括号 var multiplier = 1.0 if i < compoundFormula.endIndex && compoundFormula[i].isNumber { var numberString = "" while i < compoundFormula.endIndex && compoundFormula[i].isNumber { numberString.append(compoundFormula[i]) i = compoundFormula.index(after: i) } multiplier = Double(numberString) ?? 1.0 } // 括号内总质量乘以乘数,加上括号前的总质量 let bracketInnerTotal = totalMass * multiplier totalMass = massStack.removeLast() + bracketInnerTotal } if openParenthesesCount < 0 || openSquareBracketsCount < 0 { fatalError("括号不匹配") } } while !operatorStack.isEmpty { if operatorStack.last == "(" || operatorStack.last == "[" { fatalError("括号不匹配") } applyOperator(&totalMass, &massStack, operatorStack.removeLast()) } if openParenthesesCount != 0 || openSquareBracketsCount != 0 { fatalError("括号不匹配") } molarMass = totalMass }
关键修改点说明
- 左括号处理:新增
massStack.append(totalMass); totalMass = 0.0,将括号外已经累计的总质量暂存到栈中,重置当前总质量后专门计算括号内的元素质量。 - 右括号处理:将原来直接
totalMass *= multiplier的逻辑,改为计算括号内总质量乘以乘数后,与栈中取出的括号前总质量相加,恢复正确的累计逻辑。
内容的提问来源于stack exchange,提问作者Monte Helm
相关产品推荐
相关产品推荐

