Skill: percent-of-a-number
Percent Calculator
Three finders in one: what is P% of X, X is P% of what number, and X is what percent of Y. Every answer comes with the full working shown step by step.
1 Calculator
Pick a question type below. Nothing is hidden — every answer shows each step.
Part finder: what is P% of X?
The classic: convert the percent to a decimal, then multiply by the whole.
Whole finder: X is P% of what number?
You know the part and the percent — work backwards to the whole.
Percent finder: X is what percent of Y?
Divide the part by the whole, then multiply by 100.
"use strict"; /* Percent tool wiring: three finders (pure math in PercentTool). */ (function () { var T = window.PercentTool; function el(id) { return document.getElementById(id); }
document.querySelectorAll(".tabbtn").forEach(function (btn) { btn.addEventListener("click", function () { document.querySelectorAll(".tabbtn").forEach(function (b) { b.classList.remove("active"); }); document.querySelectorAll(".panel").forEach(function (p) { p.classList.remove("active"); }); btn.classList.add("active"); el(btn.getAttribute("data-tab")).classList.add("active"); }); });
function showErr(id, msg) { var e = el(id); if (msg) { e.textContent = msg; e.classList.add("show"); } else { e.classList.remove("show"); } } function renderSteps(ulId, steps) { el(ulId).innerHTML = steps.map(function (s) { return "
"; }).join(""); }
/* --- Finder 1: P% of X --- */ el("calc1").addEventListener("click", function () { showErr("err1", ""); var p = T.parseNonNeg(el("inP1").value), x = T.parseNonNeg(el("inX1").value); if (p === null || x === null) { showErr("err1", "Please enter the percent and the whole as numbers (0 or more)."); el("res1").classList.remove("show"); return; } var r = T.partOf(p, x); el("ans1").innerHTML = fmtPct(p) + " of " + T.fmtN(x) + " = " + r.valueText + ""; renderSteps("steps1", r.steps); var bd = T.barData(p, x); el("barFill1").style.width = bd.shownPct + "%"; el("barFill1").textContent = T.fmtN(bd.pct) + "%"; el("barLbl1a").textContent = "Part: " + r.valueText; el("barLbl1b").textContent = "Whole: " + T.fmtN(x); el("res1").classList.add("show"); }); function fmtPct(p) { return T.fmtN(p) + "%"; }
/* --- Finder 2: X is P% of what? --- */ el("calc2").addEventListener("click", function () { showErr("err2", ""); var part = T.parseNonNeg(el("inPart2").value), p = T.parseNonNeg(el("inP2").value); if (part === null || p === null) { showErr("err2", "Please enter the part and the percent as numbers (0 or more)."); el("res2").classList.remove("show"); return; } var r = T.wholeOf(part, p); if (r.error) { showErr("err2", r.error); el("res2").classList.remove("show"); return; } el("ans2").innerHTML = T.fmtN(part) + " is " + fmtPct(p) + " of " + r.valueText + ""; renderSteps("steps2", r.steps); el("res2").classList.add("show"); });
/* --- Finder 3: X is what % of Y? --- */ el("calc3").addEventListener("click", function () { showErr("err3", ""); var part = T.parseNonNeg(el("inPart3").value), whole = T.parseNonNeg(el("inWhole3").value); if (part === null || whole === null) { showErr("err3", "Please enter the part and the whole as numbers (0 or more)."); el("res3").classList.remove("show"); return; } var r = T.isWhatPct(part, whole); if (r.error) { showErr("err3", r.error); el("res3").classList.remove("show"); return; } el("ans3").innerHTML = T.fmtN(part) + " is " + r.valueText + " of " + T.fmtN(whole); renderSteps("steps3", r.steps); el("res3").classList.add("show"); }); })();
/* ============================================================ Percent Calculator Tool — pure computation core (no DOM). UMD: required by node tests as a module, inlined into tool.html as window.PercentTool. Three finders: part, whole, percent. ============================================================ */ (function (root, factory) { 'use strict'; var api = factory(); if (typeof module === 'undefined') { root.PercentTool = api; } else { module.exports = api; } })(typeof self !== 'undefined' ? self : this, function () { 'use strict';
function fmtN(v) { if (!isFinite(v)) return 'undefined'; var r = Math.round(v * 1000000) / 1000000; return String(r); } function parseNonNeg(raw) { var s = String(raw).replace(/[%$\s,]+/g, ''); if (!/^[+]?\d+(\.\d+)?$/.test(s)) return null; var v = parseFloat(s); return isFinite(v) ? v : null; }
/* Finder 1: What is P% of X? -> { value, steps[] } or { error } */ function partOf(p, x) { var v = p / 100 * x; var dec = p / 100; return { value: v, valueText: fmtN(v), steps: [ 'Write ' + fmtN(p) + '% as a decimal: ' + fmtN(p) + ' ÷ 100 = ' + fmtN(dec) + '.', '"Of" means multiply: ' + fmtN(dec) + ' × ' + fmtN(x) + ' = ' + fmtN(v) + '.', 'Sanity check: ' + fmtN(p) + '% is ' + (p < 100 ? 'less than the whole' : p > 100 ? 'more than the whole' : 'exactly the whole') + ', so the answer should be ' + (p < 100 ? 'smaller than ' : p > 100 ? 'bigger than ' : 'equal to ') + fmtN(x) + ' \u2014 and ' + fmtN(v) + ' is.' ] }; } /* Finder 2: X is P% of what number? -> { value, steps[] } or { error } */ function wholeOf(part, p) { if (p === 0) return { error: 'The percent cannot be 0 here (nothing is 0% of a nonzero whole).' }; var dec = p / 100; var v = part / dec; return { value: v, valueText: fmtN(v), steps: [ 'Write ' + fmtN(p) + '% as a decimal: ' + fmtN(dec) + '.', 'part = percent × whole, so whole = part ÷ percent.', fmtN(part) + ' ÷ ' + fmtN(dec) + ' = ' + fmtN(v) + '.', 'Check: ' + fmtN(p) + '% of ' + fmtN(v) + ' = ' + fmtN(dec * v) + '.' ] }; } /* Finder 3: X is what percent of Y? -> { value, steps[] } or { error } */ function isWhatPct(part, whole) { if (whole === 0) return { error: 'The whole cannot be 0 (cannot divide by zero).' }; var v = part / whole * 100; return { value: v, valueText: fmtN(v) + '%', steps: [ 'Divide the part by the whole: ' + fmtN(part) + ' ÷ ' + fmtN(whole) + ' = ' + fmtN(part / whole) + '.', 'Multiply by 100 to turn it into a percent: ' + fmtN(part / whole) + ' × 100 = ' + fmtN(v) + '%.', 'Sanity check: ' + fmtN(part) + ' is ' + (part < whole ? 'less than ' : part > whole ? 'more than ' : 'equal to ') + fmtN(whole) + ', so the percent should be ' + (part < whole ? 'under' : part > whole ? 'over' : 'exactly') + ' 100%.' ] }; }
/* Bar-model data for the part finder: { pct (clamped 0..100 for display), label } */ function barData(p, x) { var v = p / 100 * x; var shown = p < 0 ? 0 : (p > 100 ? 100 : p); return { pct: p, whole: x, value: v, valueText: fmtN(v), shownPct: shown }; }
return { partOf: partOf, wholeOf: wholeOf, isWhatPct: isWhatPct, barData: barData, parseNonNeg: parseNonNeg, fmtN: fmtN }; });
"use strict"; /* Percent tool wiring: three finders (pure math in PercentTool). */ (function () { var T = window.PercentTool; function el(id) { return document.getElementById(id); }
document.querySelectorAll(".tabbtn").forEach(function (btn) { btn.addEventListener("click", function () { document.querySelectorAll(".tabbtn").forEach(function (b) { b.classList.remove("active"); }); document.querySelectorAll(".panel").forEach(function (p) { p.classList.remove("active"); }); btn.classList.add("active"); el(btn.getAttribute("data-tab")).classList.add("active"); }); });
function showErr(id, msg) { var e = el(id); if (msg) { e.textContent = msg; e.classList.add("show"); } else { e.classList.remove("show"); } } function renderSteps(ulId, steps) { el(ulId).innerHTML = steps.map(function (s) { return "
"; }).join(""); }
/* --- Finder 1: P% of X --- */ el("calc1").addEventListener("click", function () { showErr("err1", ""); var p = T.parseNonNeg(el("inP1").value), x = T.parseNonNeg(el("inX1").value); if (p === null || x === null) { showErr("err1", "Please enter the percent and the whole as numbers (0 or more)."); el("res1").classList.remove("show"); return; } var r = T.partOf(p, x); el("ans1").innerHTML = fmtPct(p) + " of " + T.fmtN(x) + " = " + r.valueText + ""; renderSteps("steps1", r.steps); var bd = T.barData(p, x); el("barFill1").style.width = bd.shownPct + "%"; el("barFill1").textContent = T.fmtN(bd.pct) + "%"; el("barLbl1a").textContent = "Part: " + r.valueText; el("barLbl1b").textContent = "Whole: " + T.fmtN(x); el("res1").classList.add("show"); }); function fmtPct(p) { return T.fmtN(p) + "%"; }
/* --- Finder 2: X is P% of what? --- */ el("calc2").addEventListener("click", function () { showErr("err2", ""); var part = T.parseNonNeg(el("inPart2").value), p = T.parseNonNeg(el("inP2").value); if (part === null || p === null) { showErr("err2", "Please enter the part and the percent as numbers (0 or more)."); el("res2").classList.remove("show"); return; } var r = T.wholeOf(part, p); if (r.error) { showErr("err2", r.error); el("res2").classList.remove("show"); return; } el("ans2").innerHTML = T.fmtN(part) + " is " + fmtPct(p) + " of " + r.valueText + ""; renderSteps("steps2", r.steps); el("res2").classList.add("show"); });
/* --- Finder 3: X is what % of Y? --- */ el("calc3").addEventListener("click", function () { showErr("err3", ""); var part = T.parseNonNeg(el("inPart3").value), whole = T.parseNonNeg(el("inWhole3").value); if (part === null || whole === null) { showErr("err3", "Please enter the part and the whole as numbers (0 or more)."); el("res3").classList.remove("show"); return; } var r = T.isWhatPct(part, whole); if (r.error) { showErr("err3", r.error); el("res3").classList.remove("show"); return; } el("ans3").innerHTML = T.fmtN(part) + " is " + r.valueText + " of " + T.fmtN(whole); renderSteps("steps3", r.steps); el("res3").classList.add("show"); }); })();