fast-balanceExact chemical equation balancer
Integer/rational arithmetic, redox, charges, hydrates, isotopes and nuclear mode — with no floating-point error.
Integer/rational arithmetic, redox, charges, hydrates, isotopes and nuclear mode — with no floating-point error.
Conservation systems are solved with BigInt rational arithmetic, so coefficients are always the smallest exact integers.
Nested ()/[], ionic charges, hydrates, unicode sub/superscripts, isotope and nuclear notation, functional groups.
Spectator species are handled, genuinely underdetermined systems report every independent balance, and unknown symbols are rejected with a clear code.
The element set is validated and bounded, so balancing is O(n) in the number of species. Zero runtime dependencies.
Most balancers compute a nullspace in floating point and round the result. That fails quietly on large or stiff systems. fast-balance solves the conservation system over exact BigInt rationals and re-verifies conservation before it returns anything.
| fast-balance | Typical balancer | |
|---|---|---|
| Arithmetic | Exact BigInt rationals | Floating point |
| Large systems | Exact at any size | Silent rounding errors |
| Duplicate / spectator species | Balanced | Often rejected |
| Underdetermined systems | Minimal solution + balanceAll | Arbitrary or error |
| Unknown symbols | Typed UNKNOWN_ELEMENT error | Silent misparse |
| Complexity | O(n) in species | O(n³)-ish dense Gauss–Jordan |
.code.The site uses one flat color drawn from verdigris — the green-teal patina that forms on weathered copper (basic copper carbonate and copper acetate). It is tuned separately for light and dark mode, with no gradients, glass or glow.
import { balance, balanceAll, isBalanced, audit } from "fast-balance";
balance("H2 + O2 -> H2O").equation;
// "2 H2 + 1 O2 -> 2 H2O"
// spectator species are handled, not rejected
balance("C3H8 + O2 + N2 -> CO2 + H2O + N2").equation;
// "1 C3H8 + 5 O2 + 1 N2 -> 3 CO2 + 4 H2O + 1 N2"
// underdetermined systems return the minimal balance and are flagged
balance("C + O2 -> CO + CO2");
// { underdetermined: true, equation: "3 C + 2 O2 -> 2 CO + 1 CO2" }
balanceAll("C + O2 -> CO + CO2").map((r) => r.equation);
// ["3 C + 2 O2 -> 2 CO + 1 CO2", "4 C + 3 O2 -> 2 CO + 2 CO2"]
// unicode input works
balance("H₂ + O₂ -> H₂O").equation;
// diagnostic helpers
isBalanced("H2 + O2 -> H2O"); // true
audit("H2 + O2 -> H2O"); // element/charge totals per sidenpm install fast-balanceModern runtimes import from the package root. Pre-ES2020 / ES3 engines use fast-balance/legacy (same API, same results) — see Installation for details.
Behavior is pinned by 11 459 hand-written test cases covering every element, the combustion and oxidation ladders, notation and parsing, the solver internals, the error contract, nuclear mode, and field-by-field parity between the native and ES3 backends.