1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
| from decimal import Decimal, getcontext import re from sympy import symbols, Eq, solve, nsimplify
getcontext().prec = 100
class FormulaParser: @staticmethod def parse(formula: str) -> dict: """解析化学式返回元素组成字典""" elements = {} pattern = re.compile(r"([A-Z][a-z]?)([\d.]*)?") index = 0
while index < len(formula): match = pattern.match(formula, index) if not match: raise ValueError(f"无效化学式格式:{formula[index:]}")
elem = match.group(1) number = match.group(2)
if number == '': coeff = Decimal(1) else: try: coeff = Decimal(number) except: raise ValueError(f"无效系数:{number}")
if elem in elements: raise ValueError(f"重复元素:{elem}")
elements[elem] = coeff index = match.end()
return elements
class SynthesisCalculator: def __init__(self): self.target = {} self.reagents = [] self.molar_masses = []
def input_target(self): formula = input("请输入目标化学式(例如Li5.3PS4.3Cl0.7Br): ").strip() self.target = FormulaParser.parse(formula) print(f"已解析目标化合物: {self.target}")
def input_reagents(self): num = int(input("请输入原料种数: ")) for i in range(num): formula = input(f"原料{i+1}化学式: ").strip() try: parsed = FormulaParser.parse(formula) self.reagents.append(parsed) mm = Decimal(input(f"原料{i+1}摩尔质量(g/mol): ").strip()) self.molar_masses.append(mm) except Exception as e: print(f"输入错误: {e}") exit()
def validate_elements(self): target_elements = set(self.target.keys()) provided = set() for r in self.reagents: provided.update(r.keys()) missing = target_elements - provided if missing: print(f"错误:缺少以下元素: {', '.join(missing)}") exit()
def build_equations(self, n: Decimal): variables = symbols(f'x0:{len(self.reagents)}') equations = []
for element, coeff in self.target.items(): lhs = sum( var * Decimal(str(reagent.get(element, 0.0))) for var, reagent in zip(variables, self.reagents) ) equations.append(Eq(lhs, coeff * n))
return variables, equations
def solve(self, n: Decimal): variables, equations = self.build_equations(n) try: solution = solve(equations, variables, dict=True) if not solution: print("无可行解:原料配比无法满足目标成分") exit() decimal_solution = [] for sol in solution: new_sol = {} for k, v in sol.items(): new_sol[k] = Decimal(str(nsimplify(v).evalf(50))) decimal_solution.append(new_sol) return decimal_solution except Exception as e: print(f"求解错误: {e}") exit()
def calculate(self): n = Decimal(input("请输入目标物质的量(mol): ").strip()) solution = self.solve(n)[0]
print("\n" + "="*60) print(f"合成 {n} mol 目标化合物需要:")
total_mass = Decimal(0) for i, (var, moles) in enumerate(solution.items()): if moles < 0: print(f"错误:{var} 的摩尔量为负值") exit()
mass = moles * self.molar_masses[i] total_mass += mass
print(f"原料{i+1}:") print(f" 化学式: {self.reagents[i]}") print(f" 需要量: {moles.normalize():.50f} mol") print(f" 质量: {mass.normalize():.50f} g\n")
print(f"总质量: {total_mass.normalize():.50f} g")
def main(): print("高精度化合物合成计算器") print("="*60)
calc = SynthesisCalculator() calc.input_target() calc.input_reagents() calc.validate_elements() calc.calculate()
if __name__ == "__main__": main()
|