Cómo calcular masa molar con un parser pequeño y sin usar eval

Una fórmula química parece una cadena sencilla, pero contiene símbolos, cantidades y paréntesis. Convertirla directamente con eval() sería incorrecto y peligroso; necesitamos una gramática mínima y una tabla de masas.

El problema y el alcance del ejemplo

La ficha de ElementalHub: Tabla periódica resume su función así: «Tabla periódica interactiva, calculadora de masa molar e isótopos sin conexión.» ElementalHub describe tabla periódica y calculadora de masa molar sin conexión. Este tutorial implementa un parser limitado y explícito como ejercicio de programación, no el motor científico de la aplicación.

Cómo reproducir la idea

Utiliza Python 3. Guarda el código como masa_molar.py y ejecútalo. La tabla contiene solo cuatro elementos de ejemplo.

import re from decimal import Decimal MASAS = {"H": Decimal("1.008"), "O": Decimal("15.999"), "C": Decimal("12.011"), "Ca": Decimal("40.078")} def masa_molar(formula): tokens = re.findall(r'[A-Z][a-z]?|[1-9][0-9]*|[()]', formula) if ''.join(tokens) != formula or not tokens: raise ValueError('Fórmula inválida') pos = 0 def grupo(): nonlocal pos total = Decimal('0') while pos < len(tokens) and tokens[pos] != ')': token = tokens[pos] pos += 1 if token == '(': value = grupo() if pos >= len(tokens) or tokens[pos] != ')': raise ValueError('Paréntesis sin cerrar') pos += 1 elif token in MASAS: value = MASAS[token] else: raise ValueError('Elemento u operador no admitido: ' + token) factor = 1 if pos < len(tokens) and tokens[pos].isdigit(): factor = int(tokens[pos]); pos += 1 total += value * factor return total result = grupo() if pos != len(tokens): raise ValueError('Paréntesis no balanceados') return result for f in ['H2O', 'CO2', 'Ca(OH)2']: print(f, masa_molar(f), 'g/mol') 

Qué demuestra el código

El tokenizador distingue símbolos químicos de multiplicadores. La función recursiva procesa paréntesis y multiplica la contribución de cada grupo. El resultado usa Decimal, lo que ayuda a controlar la representación de las masas proporcionadas.

Pruebas recomendadas

Comprueba que H2O da aproximadamente 18.015 g/mol, CO2 cerca de 44.009 g/mol y Ca(OH)2 cerca de 74.092 g/mol. Prueba un símbolo desconocido o un paréntesis sin cerrar para ver la validación.

Límites que conviene reconocer

El parser no admite cargas, hidratos con punto, coeficientes de reacción ni todos los elementos. Las masas usadas son redondeos de ejemplo; distintos isótopos y convenciones pueden cambiar el cálculo. No debe tratarse como referencia de laboratorio validada.

Qué aprendemos

Las herramientas científicas necesitan tanto un parser de entrada verificable como un conjunto de datos con fuentes y unidades conocidas.

Contexto y enlaces del autor

El tema se relaciona con las funciones declaradas públicamente de ElementalHub: Tabla periódica, una aplicación Android de AppInitDev. El código anterior es un ejemplo independiente: no se ha inspeccionado el repositorio privado ni se afirma que sea la implementación interna de la app. La referencia aparece al final para ofrecer contexto, no como requisito para completar el tutorial.

Image APPS

Referencia técnica

IUPAC: Standard atomic weights