Skill: multi-step-equations
Multi-Step Equation Solver
Type any linear equation — parentheses, fractions, decimals, variables on both sides — and see every step.
Solve a multi-step equation
Handles parentheses, fractions, decimals, and x on both sides. Detects no-solution and infinite-solution cases.
Check a proposed solution
Substitutes your value into both sides and compares.
(function(){ 'use strict'; var btns = document.querySelectorAll('.tabbtn'); btns.forEach(function(b){ b.addEventListener('click', function(){ btns.forEach(function(x){ x.classList.remove('active'); }); document.querySelectorAll('.panel').forEach(function(p){ p.classList.remove('active'); }); b.classList.add('active'); document.getElementById(b.getAttribute('data-tab')).classList.add('active'); }); }); })();
// __PURE_BEGIN__
var TOOL_API = (function(){
'use strict';
function N(x, c){ return {x:x, c:c}; }
function addn(p, q){ return {x:p.x + q.x, c:p.c + q.c}; }
function muln(p, q){
if (p.x !== 0){
if (q.x !== 0) return null;
} else if (q.x !== 0){ var t = p; p = q; q = t; }
return {x:p.x * q.c, c:p.c * q.c};
}
function tokenize(s){
var raw = [], i = 0;
s = String(s).toLowerCase().replace(/\s+/g, '').replace(/×/g, '*');
while (i < s.length){
var ch = s[i];
if ('+-*/()'.indexOf(ch) >= 0){ raw.push(ch); i++; continue; }
if (/[0-9.]/.test(ch)){
var j = i;
while (j < s.length){
if (!/[0-9.]/.test(s[j])) break;
j++;
}
raw.push(s.slice(i, j)); i = j; continue;
}
if (ch === 'x'){ raw.push('x'); i++; continue; }
return null;
}
var toks = [];
for (var k = 0; k < raw.length; k++){
toks.push(raw[k]);
var a = raw[k], b = raw[k + 1];
var aIsVal = /^[0-9.]+$/.test(a) || a === ')' || a === 'x';
if (aIsVal){
if (b === '(' || b === 'x'){
if (a !== 'x' || b !== 'x') toks.push('*');
}
}
}
return toks;
}
function parseSide(s){
var toks = tokenize(s);
if (!toks || toks.length === 0) return null;
var pos = 0;
function peek(){ return pos < toks.length ? toks[pos] : null; }
function P(){
if (peek() === '-'){ pos++; var a = P(); if (!a) return null; return N(-a.x, -a.c); }
if (peek() === '+'){ pos++; return P(); }
var tk = toks[pos++];
if (tk === '('){ var n = E(); if (!n) return null; if (toks[pos++] !== ')') return null; return n; }
if (tk === 'x') return N(1, 0);
if (/^[0-9.]+$/.test(tk)) return N(0, parseFloat(tk));
return null;
}
function F(){
var n = P();
if (!n) return null;
while (peek() === '*' || peek() === '/'){
var o = toks[pos++], r = P();
if (!r) return null;
if (o === '*') n = muln(n, r);
else {
if (r.x !== 0 || r.c === 0) return null;
n = muln(n, N(0, 1 / r.c));
}
if (!n) return null;
}
return n;
}
function E(){
var n = F();
if (!n) return null;
while (peek() === '+' || peek() === '-'){
var o = toks[pos++], r = F();
if (!r) return null;
n = o === '+' ? addn(n, r) : addn(n, N(-r.x, -r.c));
}
return n;
}
var n = E();
if (!n || pos !== toks.length) return null;
return n;
}
function fmtNum(n){
var r = Math.round(n * 1e10) / 1e10;
if (r === Math.round(r)) return String(Math.round(r));
return String(r);
}
function fmtLin(x, c){
var xs = x === 1 ? 'x' : x === -1 ? '−x' : fmtNum(x) + 'x';
if (c === 0) return x === 0 ? '0' : xs;
if (x === 0) return fmtNum(c);
return xs + (c > 0 ? ' + ' + fmtNum(c) : ' − ' + fmtNum(-c));
}
function gcd(a, b){ a = Math.abs(Math.round(a)); b = Math.abs(Math.round(b)); while (b){ var t = a % b; a = b; b = t; } return a || 1; }
function fracStr(num, den){
if (Math.abs(den) < 1e-12) return 'undefined';
var v = num / den;
if (Math.abs(v - Math.round(v)) < 1e-9) return String(Math.round(v));
var n = Math.round(num * 1e6), d = Math.round(den * 1e6);
var g = gcd(n, d);
n = n / g; d = d / g;
if (d < 0){ n = -n; d = -d; }
return n + '/' + d;
}
function solve(eqStr){
var parts = String(eqStr).split('=');
if (parts.length !== 2) return {ok:false, error:'Use one = sign, e.g. 2(x+1)=3x-1.'};
var L = parseSide(parts[0]), R = parseSide(parts[1]);
if (!L || !R) return {ok:false, error:'Could not read that. Use numbers, x, +, −, ×, ÷, and parentheses.'};
var steps = [];
steps.push('Simplify each side: ' + fmtLin(L.x, L.c) + ' = ' + fmtLin(R.x, R.c) + '.');
var kx = L.x - R.x, kn = R.c - L.c;
if (Math.abs(kx) < 1e-12){
if (Math.abs(kn) < 1e-12){
steps.push('The x-terms cancel and 0 = 0 is always true.');
return {ok:true, special:'infinite', steps:steps};
}
steps.push('The x-terms cancel and 0 = ' + fmtNum(kn) + ' is never true.');
return {ok:true, special:'none', steps:steps};
}
steps.push('Collect x-terms: ' + fmtLin(kx, 0) + ' = ' + fmtNum(kn) + '.');
var xs = fracStr(kn, kx);
steps.push('Divide by ' + fmtNum(kx) + ': x = ' + xs + '.');
return {ok:true, x:kn / kx, xStr:xs, steps:steps};
}
function checkSol(eqStr, xStr){
var parts = String(eqStr).split('=');
if (parts.length !== 2) return {ok:false, error:'Use one = sign.'};
var L = parseSide(parts[0]), R = parseSide(parts[1]);
if (!L || !R) return {ok:false, error:'Could not read the equation.'};
var x = parseFloat(String(xStr).trim());
if (isNaN(x)) return {ok:false, error:'Enter a number for x.'};
var lhs = L.x * x + L.c, rhs = R.x * x + R.c;
var good = Math.abs(lhs - rhs) < 1e-9;
return {ok:true, good:good, lhs:lhs, rhs:rhs,
steps:['Substitute x = ' + fmtNum(x) + ': left = ' + fmtNum(lhs) + ', right = ' + fmtNum(rhs) + '.',
good ? 'Both sides match — x = ' + fmtNum(x) + ' is a solution.' : 'They differ — x = ' + fmtNum(x) + ' is NOT a solution.']};
}
return {parseSide:parseSide, solve:solve, checkSol:checkSol};
})();
// __PURE_END__
(function(){ 'use strict'; function $(id){ return document.getElementById(id); } function esc(s){ return String(s).replace(/\x26/g,'&').replace(//g,'>'); } document.addEventListener('DOMContentLoaded', function(){ function runSolve(){ var r = TOOL_API.solve($('eq').value); var err = $('errS'), res = $('resS'); err.classList.remove('show'); res.classList.remove('show'); if (!r.ok){ err.textContent = r.error; err.classList.add('show'); return; } var ans = r.special === 'infinite' ? 'Infinitely many solutions' : r.special === 'none' ? 'No solution' : 'x = ' + esc(r.xStr); $('ansS').innerHTML = '' + ans + ''; $('stepsS').innerHTML = r.steps.map(function(s){ return '
'; }).join(''); res.classList.add('show'); } function runCheck(){ var r = TOOL_API.checkSol($('ceq').value, $('cx').value); var err = $('errC'), res = $('resC'); err.classList.remove('show'); res.classList.remove('show'); if (!r.ok){ err.textContent = r.error; err.classList.add('show'); return; } $('ansC').innerHTML = r.good ? 'Yes — it checks out.' : 'No — it does not satisfy the equation.'; $('stepsC').innerHTML = r.steps.map(function(s){ return '
'; }).join(''); res.classList.add('show'); } $('calcS').addEventListener('click', runSolve); $('calcC').addEventListener('click', runCheck); }); })();