Equivalent Fractions Worksheet Generator
Generate a fresh 20-problem practice set: building fractions up, simplifying to lowest terms, filling in missing numbers, and true-or-false equivalence checks.
Skill: fraction-equivalence
Equivalent Fractions Practice Worksheet
Answer Key
For the teacher or for self-checking after you finish.
'use strict'; /* == PURE (tested by test_worksheet.js via window.__WS) == */ function mulberry32(a){ return function(){ a |= 0; a = (a + 0x6D2B79F5) | 0; var t = Math.imul(a ^ (a >>> 15), 1 | a); t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t; return ((t ^ (t >>> 14)) >>> 0) / 4294967296; }; } var _rand = Math.random; function setSeed(s){ _rand = mulberry32(s >>> 0); } function ri(lo, hi){ return lo + Math.floor(_rand() * (hi - lo + 1)); } function pick(arr){ return arr[Math.floor(_rand() * arr.length)]; } function chance(p){ return _rand() < p; } function shuffle(a){ for (var i = a.length - 1; i > 0; i--){ var j = Math.floor(_rand() * (i + 1)); var t = a[i]; a[i] = a[j]; a[j] = t; } return a; } function wgcd(a, b){ a = Math.abs(a); b = Math.abs(b); while (b !== 0){ var t = a % b; a = b; b = t; } return a === 0 ? 1 : a; } function wreduce(n, d){ if (d === 0) throw new Error('wreduce: zero denominator'); if (d < 0){ n = -n; d = -d; } if (n === 0) return [0, 1]; var g = wgcd(n, d); return [n / g, d / g]; } /* worksheet stacked fraction: uses .fnum/.fden classes */ function wfrac(n, d){ var sign = n < 0 ? '−' : ''; if (d === 1) return '' + sign + Math.abs(n) + ''; return sign + '' + Math.abs(n) + '' + d + ''; } function rfrac(loD, hiD, hiN){ /* random reduced proper fraction */ for (var t = 0; t < 60; t++){ var d = ri(loD, hiD), n = ri(1, Math.min(hiN, d - 1)); if (wgcd(n, d) === 1) return [n, d]; } return [1, 2]; } function genBuildUp(diff){ var cfg = { easy: [2, 6, 4], medium: [2, 10, 6], hard: [2, 12, 9] }[diff]; var nd = rfrac(cfg[0], cfg[1], 9), n = nd[0], d = nd[1], k = ri(2, cfg[2]); var D = d * k; return { kind: 'build-up', params: { n: n, d: d, k: k, D: D }, stemHTML: 'Rename ' + wfrac(n, d) + ' as an equivalent fraction with denominator ' + D + '.', answerHTML: wfrac(n * k, D), answer: { k: 'f', n: n * k, d: D } }; } function genSimplify(diff){ var cfg = { easy: [2, 6, 4], medium: [2, 10, 5], hard: [2, 12, 7] }[diff]; var nd = rfrac(cfg[0], cfg[1], 9), rn = nd[0], rd = nd[1], k = ri(2, cfg[2]); var n = rn * k, d = rd * k; return { kind: 'simplify', params: { n: n, d: d, rn: rn, rd: rd, g: k }, stemHTML: 'Simplify ' + wfrac(n, d) + ' to lowest terms.', answerHTML: wfrac(rn, rd), answer: { k: 'f', n: rn, d: rd } }; } function genMissing(diff){ var cfg = { easy: [2, 6, 4], medium: [2, 10, 6], hard: [2, 12, 9] }[diff]; var nd = rfrac(cfg[0], cfg[1], 9), n = nd[0], d = nd[1], k = ri(2, cfg[2]); var N = n * k, D = d * k; var top = chance(0.5); return { kind: 'missing', params: { n: n, d: d, k: k, N: N, D: D, top: top }, stemHTML: top ? 'Fill in the missing number: ' + wfrac(n, d) + ' = ?/' + D + '.' : 'Fill in the missing number: ' + wfrac(n, d) + ' = ' + N + '/?.', answerHTML: '' + (top ? N : D) + '', answer: { k: 'int', v: top ? N : D } }; } function genEquivTF(diff){ var cfg = { easy: [2, 6], medium: [2, 9], hard: [2, 12] }[diff]; var nd = rfrac(cfg[0], cfg[1], 9), n = nd[0], d = nd[1]; var eq = chance(0.5); var c, dd; if (eq) { var k = ri(2, 5); c = n * k; dd = d * k; } else { var k2 = ri(2, 4); c = n * k2 + 1; dd = d * k2; if (c >= dd) { c = n * k2 - 1; } } return { kind: 'equiv-tf', params: { a: n, b: d, c: c, d: dd, eq: eq }, stemHTML: 'True or false: ' + wfrac(n, d) + ' = ' + wfrac(c, dd) + '.', answerHTML: '' + (eq ? 'True' : 'False') + '', answer: { k: 'tf', v: eq } }; } var TYPE_PLAN = [ genBuildUp, genBuildUp, genBuildUp, genBuildUp, genBuildUp, genBuildUp, genSimplify, genSimplify, genSimplify, genSimplify, genSimplify, genSimplify, genMissing, genMissing, genMissing, genMissing, genEquivTF, genEquivTF, genEquivTF, genEquivTF ]; function generateSet(seed, difficulty){ if (['easy','medium','hard'].indexOf(difficulty) === -1) throw new Error('generateSet: bad difficulty ' + difficulty); setSeed(seed >>> 0); var plan = shuffle(TYPE_PLAN.slice()); var problems = plan.map(function(gen){ return gen(difficulty); }); if (problems.length !== 20) throw new Error('generateSet: expected 20 problems'); return problems; } /* == /PURE == */
var current = { problems: [], difficulty: 'medium', keyVisible: false, seed: 0, genCount: 0 }; var el = {}; function renderProblems(){ el.problems.innerHTML = current.problems.map(function(p, i){ return '
'; }).join(''); el.probCount.textContent = current.problems.length + ' problems · ' + current.difficulty.charAt(0).toUpperCase() + current.difficulty.slice(1); } function renderKey(){ el.keyGrid.innerHTML = current.problems.map(function(p, i){ return '
'; }).join(''); } function newSet(seed){ current.seed = (seed === undefined) ? ((Date.now() + (current.genCount * 7919)) >>> 0) : (seed >>> 0); current.genCount++; current.problems = generateSet(current.seed, current.difficulty); renderProblems(); if (current.keyVisible) renderKey(); } function setKeyVisible(v){ current.keyVisible = v; el.keySection.hidden = !v; el.btnKey.setAttribute('aria-pressed', v ? 'true' : 'false'); el.btnKey.textContent = v ? 'Hide Answer Key' : 'Show Answer Key'; if (v) renderKey(); } function init(){ el.diffSel = document.getElementById('diffSel'); el.btnGen = document.getElementById('btnGen'); el.btnKey = document.getElementById('btnKey'); el.btnPrint = document.getElementById('btnPrint'); el.problems = document.getElementById('problems'); el.probCount = document.getElementById('probCount'); el.keySection= document.getElementById('keySection'); el.keyGrid = document.getElementById('keyGrid'); current.difficulty = el.diffSel.value; el.diffSel.addEventListener('change', function(){ current.difficulty = el.diffSel.value; newSet(); }); el.btnGen.addEventListener('click', function(){ newSet(); }); el.btnKey.addEventListener('click', function(){ setKeyVisible(!current.keyVisible); }); el.btnPrint.addEventListener('click', function(){ window.print(); }); newSet(); } if (document.readyState === 'loading'){ document.addEventListener('DOMContentLoaded', init); } else { init(); } window.__WS = { generateSet: generateSet, wreduce: wreduce, wfrac: wfrac, getState: function(){ return current; }, newSet: newSet, setKeyVisible: setKeyVisible };
'use strict'; /* == PURE (tested by test_worksheet.js via window.__WS) == */ function mulberry32(a){ return function(){ a |= 0; a = (a + 0x6D2B79F5) | 0; var t = Math.imul(a ^ (a >>> 15), 1 | a); t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t; return ((t ^ (t >>> 14)) >>> 0) / 4294967296; }; } var _rand = Math.random; function setSeed(s){ _rand = mulberry32(s >>> 0); } function ri(lo, hi){ return lo + Math.floor(_rand() * (hi - lo + 1)); } function pick(arr){ return arr[Math.floor(_rand() * arr.length)]; } function chance(p){ return _rand() < p; } function shuffle(a){ for (var i = a.length - 1; i > 0; i--){ var j = Math.floor(_rand() * (i + 1)); var t = a[i]; a[i] = a[j]; a[j] = t; } return a; } function wgcd(a, b){ a = Math.abs(a); b = Math.abs(b); while (b !== 0){ var t = a % b; a = b; b = t; } return a === 0 ? 1 : a; } function wreduce(n, d){ if (d === 0) throw new Error('wreduce: zero denominator'); if (d < 0){ n = -n; d = -d; } if (n === 0) return [0, 1]; var g = wgcd(n, d); return [n / g, d / g]; } /* worksheet stacked fraction: uses .fnum/.fden classes */ function wfrac(n, d){ var sign = n < 0 ? '−' : ''; if (d === 1) return '' + sign + Math.abs(n) + ''; return sign + '' + Math.abs(n) + '' + d + ''; } function rfrac(loD, hiD, hiN){ /* random reduced proper fraction */ for (var t = 0; t < 60; t++){ var d = ri(loD, hiD), n = ri(1, Math.min(hiN, d - 1)); if (wgcd(n, d) === 1) return [n, d]; } return [1, 2]; } function genBuildUp(diff){ var cfg = { easy: [2, 6, 4], medium: [2, 10, 6], hard: [2, 12, 9] }[diff]; var nd = rfrac(cfg[0], cfg[1], 9), n = nd[0], d = nd[1], k = ri(2, cfg[2]); var D = d * k; return { kind: 'build-up', params: { n: n, d: d, k: k, D: D }, stemHTML: 'Rename ' + wfrac(n, d) + ' as an equivalent fraction with denominator ' + D + '.', answerHTML: wfrac(n * k, D), answer: { k: 'f', n: n * k, d: D } }; } function genSimplify(diff){ var cfg = { easy: [2, 6, 4], medium: [2, 10, 5], hard: [2, 12, 7] }[diff]; var nd = rfrac(cfg[0], cfg[1], 9), rn = nd[0], rd = nd[1], k = ri(2, cfg[2]); var n = rn * k, d = rd * k; return { kind: 'simplify', params: { n: n, d: d, rn: rn, rd: rd, g: k }, stemHTML: 'Simplify ' + wfrac(n, d) + ' to lowest terms.', answerHTML: wfrac(rn, rd), answer: { k: 'f', n: rn, d: rd } }; } function genMissing(diff){ var cfg = { easy: [2, 6, 4], medium: [2, 10, 6], hard: [2, 12, 9] }[diff]; var nd = rfrac(cfg[0], cfg[1], 9), n = nd[0], d = nd[1], k = ri(2, cfg[2]); var N = n * k, D = d * k; var top = chance(0.5); return { kind: 'missing', params: { n: n, d: d, k: k, N: N, D: D, top: top }, stemHTML: top ? 'Fill in the missing number: ' + wfrac(n, d) + ' = ?/' + D + '.' : 'Fill in the missing number: ' + wfrac(n, d) + ' = ' + N + '/?.', answerHTML: '' + (top ? N : D) + '', answer: { k: 'int', v: top ? N : D } }; } function genEquivTF(diff){ var cfg = { easy: [2, 6], medium: [2, 9], hard: [2, 12] }[diff]; var nd = rfrac(cfg[0], cfg[1], 9), n = nd[0], d = nd[1]; var eq = chance(0.5); var c, dd; if (eq) { var k = ri(2, 5); c = n * k; dd = d * k; } else { var k2 = ri(2, 4); c = n * k2 + 1; dd = d * k2; if (c >= dd) { c = n * k2 - 1; } } return { kind: 'equiv-tf', params: { a: n, b: d, c: c, d: dd, eq: eq }, stemHTML: 'True or false: ' + wfrac(n, d) + ' = ' + wfrac(c, dd) + '.', answerHTML: '' + (eq ? 'True' : 'False') + '', answer: { k: 'tf', v: eq } }; } var TYPE_PLAN = [ genBuildUp, genBuildUp, genBuildUp, genBuildUp, genBuildUp, genBuildUp, genSimplify, genSimplify, genSimplify, genSimplify, genSimplify, genSimplify, genMissing, genMissing, genMissing, genMissing, genEquivTF, genEquivTF, genEquivTF, genEquivTF ]; function generateSet(seed, difficulty){ if (['easy','medium','hard'].indexOf(difficulty) === -1) throw new Error('generateSet: bad difficulty ' + difficulty); setSeed(seed >>> 0); var plan = shuffle(TYPE_PLAN.slice()); var problems = plan.map(function(gen){ return gen(difficulty); }); if (problems.length !== 20) throw new Error('generateSet: expected 20 problems'); return problems; } /* == /PURE == */
var current = { problems: [], difficulty: 'medium', keyVisible: false, seed: 0, genCount: 0 }; var el = {}; function renderProblems(){ el.problems.innerHTML = current.problems.map(function(p, i){ return '
'; }).join(''); el.probCount.textContent = current.problems.length + ' problems · ' + current.difficulty.charAt(0).toUpperCase() + current.difficulty.slice(1); } function renderKey(){ el.keyGrid.innerHTML = current.problems.map(function(p, i){ return '
'; }).join(''); } function newSet(seed){ current.seed = (seed === undefined) ? ((Date.now() + (current.genCount * 7919)) >>> 0) : (seed >>> 0); current.genCount++; current.problems = generateSet(current.seed, current.difficulty); renderProblems(); if (current.keyVisible) renderKey(); } function setKeyVisible(v){ current.keyVisible = v; el.keySection.hidden = !v; el.btnKey.setAttribute('aria-pressed', v ? 'true' : 'false'); el.btnKey.textContent = v ? 'Hide Answer Key' : 'Show Answer Key'; if (v) renderKey(); } function init(){ el.diffSel = document.getElementById('diffSel'); el.btnGen = document.getElementById('btnGen'); el.btnKey = document.getElementById('btnKey'); el.btnPrint = document.getElementById('btnPrint'); el.problems = document.getElementById('problems'); el.probCount = document.getElementById('probCount'); el.keySection= document.getElementById('keySection'); el.keyGrid = document.getElementById('keyGrid'); current.difficulty = el.diffSel.value; el.diffSel.addEventListener('change', function(){ current.difficulty = el.diffSel.value; newSet(); }); el.btnGen.addEventListener('click', function(){ newSet(); }); el.btnKey.addEventListener('click', function(){ setKeyVisible(!current.keyVisible); }); el.btnPrint.addEventListener('click', function(){ window.print(); }); newSet(); } if (document.readyState === 'loading'){ document.addEventListener('DOMContentLoaded', init); } else { init(); } window.__WS = { generateSet: generateSet, wreduce: wreduce, wfrac: wfrac, getState: function(){ return current; }, newSet: newSet, setKeyVisible: setKeyVisible };