Choose a number below — or type your own — and the demo will peel it into a continued fraction. Each row is a convergent: the fraction you get by stopping at that term. Watch the error column shrink dramatically with every step, and notice the famous fractions appearing on their own.
<p class="hint">Pick a number or type your own, then peel it into a continued fraction.
Each row is a <b>convergent</b> — the fraction you get by stopping there. Watch the
<b>error</b> column collapse, and the famous fractions appear on their own.</p>
<div class="controls">
<button type="button" data-x="3.141592653589793" data-n="π">π</button>
<button type="button" data-x="1.618033988749895" data-n="golden ratio φ">φ (golden)</button>
<button type="button" data-x="1.4142135623730951" data-n="√2">√2</button>
<button type="button" data-x="2.718281828459045" data-n="e">e</button>
<button type="button" data-x="365.2422" data-n="days in a year">365.2422 (year)</button>
</div>
<div class="custom">
<input id="num" type="text" value="3.141592653589793" aria-label="number" />
<button id="go" type="button">Expand</button>
</div>
<div class="cf" id="cf"></div>
<table class="conv"><thead><tr><th>term</th><th>convergent</th><th>value</th><th>error</th></tr></thead>
<tbody id="rows"></tbody></table>
* { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; color: #222; margin: 0; }
.hint { font-size: .9rem; color: #444; margin: 0 0 .7rem; line-height: 1.45; }
.controls { display: flex; gap: .4rem; flex-wrap: wrap; margin-bottom: .5rem; }
.controls button { font: 600 13px system-ui, sans-serif; padding: .4rem .7rem; border: 1px solid #1d3557;
background: #eef3f8; color: #1d3557; border-radius: 8px; cursor: pointer; }
.controls button:hover { background: #dce6f0; }
.custom { display: flex; gap: .4rem; margin-bottom: .8rem; }
.custom input { flex: 1; font: 600 14px ui-monospace, monospace; padding: .4rem .6rem;
border: 1px solid #cdd9e3; border-radius: 8px; min-width: 0; }
.custom button { font: 600 14px system-ui, sans-serif; padding: .4rem .9rem; border: 1px solid #1d3557;
background: #1d3557; color: #fff; border-radius: 8px; cursor: pointer; }
.cf { font: 600 15px ui-monospace, monospace; color: #1d3557; background: #f3f6fa;
border: 1px solid #dde6ee; border-radius: 8px; padding: .6rem .7rem; margin-bottom: .8rem;
word-break: break-word; }
table.conv { border-collapse: collapse; width: 100%; font-size: .9rem; }
table.conv th, table.conv td { text-align: left; padding: .35rem .5rem; border-bottom: 1px solid #e6ecf2; }
table.conv th { color: #5a7088; font-weight: 700; }
table.conv td { font-family: ui-monospace, monospace; }
td.frac { font-weight: 700; color: #1d3557; }
td.err { color: #0a7d33; }
tr.famous td.frac { background: #fff3cd; border-radius: 6px; }
// Continued fraction expansion: write the whole part, take the reciprocal of the
// leftover, repeat. Convergents h_n/k_n use the recurrence
// h_n = a_n*h_{n-1} + h_{n-2}, k_n = a_n*k_{n-1} + k_{n-2}.
// Lagrange's theorem (18th c.): each convergent is the BEST rational approximation
// among all fractions with denominator <= its own. Classical, solved mathematics.
const FAMOUS = new Set(['22/7','355/113','3/2','7/5','17/12','1/4','365/1']);
function expand(x){
const terms=[]; const conv=[];
let v=x, hm1=1,hm2=0,km1=0,km2=1;
for(let i=0;i<12;i++){
const a=Math.floor(v); terms.push(a);
const h=a*hm1+hm2, k=a*km1+km2;
conv.push([h,k]);
hm2=hm1; hm1=h; km2=km1; km1=k;
const frac=v-a;
if(frac < 1e-10) break; // rational / numerical floor reached
v=1/frac;
if(k > 1e9) break; // keep denominators readable
}
return {terms, conv};
}
function fmtCF(terms){
if(terms.length===1) return '[' + terms[0] + ']';
return '[' + terms[0] + '; ' + terms.slice(1).join(', ') + ']';
}
function show(x, name){
const {terms, conv} = expand(x);
document.getElementById('cf').textContent =
(name?name+' = ':'') + fmtCF(terms);
const tb=document.getElementById('rows'); tb.innerHTML='';
conv.forEach(([h,k],i)=>{
const val=h/k, err=Math.abs(x-val);
const tr=document.createElement('tr');
const key=h+'/'+k;
if(FAMOUS.has(key)) tr.className='famous';
tr.innerHTML =
'<td>'+terms[i]+'</td>'+
'<td class="frac">'+key+'</td>'+
'<td>'+val.toFixed(8)+'</td>'+
'<td class="err">'+(err===0?'exact':err.toExponential(2))+'</td>';
tb.appendChild(tr);
});
console.log(name||x, '->', fmtCF(terms),
'| best convergent', conv[conv.length-1].join('/'));
}
document.querySelectorAll('.controls button').forEach(b=>{
b.addEventListener('click',()=>{
document.getElementById('num').value=b.dataset.x;
show(parseFloat(b.dataset.x), b.dataset.n);
});
});
document.getElementById('go').addEventListener('click',()=>{
const x=parseFloat(document.getElementById('num').value);
if(isFinite(x)) show(x, '');
else document.getElementById('cf').textContent='Enter a valid number.';
});
show(Math.PI, 'π');
<p class="hint">Pick a number or type your own, then peel it into a continued fraction.
Each row is a <b>convergent</b> — the fraction you get by stopping there. Watch the
<b>error</b> column collapse, and the famous fractions appear on their own.</p>
<div class="controls">
<button type="button" data-x="3.141592653589793" data-n="π">π</button>
<button type="button" data-x="1.618033988749895" data-n="golden ratio φ">φ (golden)</button>
<button type="button" data-x="1.4142135623730951" data-n="√2">√2</button>
<button type="button" data-x="2.718281828459045" data-n="e">e</button>
<button type="button" data-x="365.2422" data-n="days in a year">365.2422 (year)</button>
</div>
<div class="custom">
<input id="num" type="text" value="3.141592653589793" aria-label="number" />
<button id="go" type="button">Expand</button>
</div>
<div class="cf" id="cf"></div>
<table class="conv"><thead><tr><th>term</th><th>convergent</th><th>value</th><th>error</th></tr></thead>
<tbody id="rows"></tbody></table>
* { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; color: #222; margin: 0; }
.hint { font-size: .9rem; color: #444; margin: 0 0 .7rem; line-height: 1.45; }
.controls { display: flex; gap: .4rem; flex-wrap: wrap; margin-bottom: .5rem; }
.controls button { font: 600 13px system-ui, sans-serif; padding: .4rem .7rem; border: 1px solid #1d3557;
background: #eef3f8; color: #1d3557; border-radius: 8px; cursor: pointer; }
.controls button:hover { background: #dce6f0; }
.custom { display: flex; gap: .4rem; margin-bottom: .8rem; }
.custom input { flex: 1; font: 600 14px ui-monospace, monospace; padding: .4rem .6rem;
border: 1px solid #cdd9e3; border-radius: 8px; min-width: 0; }
.custom button { font: 600 14px system-ui, sans-serif; padding: .4rem .9rem; border: 1px solid #1d3557;
background: #1d3557; color: #fff; border-radius: 8px; cursor: pointer; }
.cf { font: 600 15px ui-monospace, monospace; color: #1d3557; background: #f3f6fa;
border: 1px solid #dde6ee; border-radius: 8px; padding: .6rem .7rem; margin-bottom: .8rem;
word-break: break-word; }
table.conv { border-collapse: collapse; width: 100%; font-size: .9rem; }
table.conv th, table.conv td { text-align: left; padding: .35rem .5rem; border-bottom: 1px solid #e6ecf2; }
table.conv th { color: #5a7088; font-weight: 700; }
table.conv td { font-family: ui-monospace, monospace; }
td.frac { font-weight: 700; color: #1d3557; }
td.err { color: #0a7d33; }
tr.famous td.frac { background: #fff3cd; border-radius: 6px; }
// Continued fraction expansion: write the whole part, take the reciprocal of the
// leftover, repeat. Convergents h_n/k_n use the recurrence
// h_n = a_n*h_{n-1} + h_{n-2}, k_n = a_n*k_{n-1} + k_{n-2}.
// Lagrange's theorem (18th c.): each convergent is the BEST rational approximation
// among all fractions with denominator <= its own. Classical, solved mathematics.
const FAMOUS = new Set(['22/7','355/113','3/2','7/5','17/12','1/4','365/1']);
function expand(x){
const terms=[]; const conv=[];
let v=x, hm1=1,hm2=0,km1=0,km2=1;
for(let i=0;i<12;i++){
const a=Math.floor(v); terms.push(a);
const h=a*hm1+hm2, k=a*km1+km2;
conv.push([h,k]);
hm2=hm1; hm1=h; km2=km1; km1=k;
const frac=v-a;
if(frac < 1e-10) break; // rational / numerical floor reached
v=1/frac;
if(k > 1e9) break; // keep denominators readable
}
return {terms, conv};
}
function fmtCF(terms){
if(terms.length===1) return '[' + terms[0] + ']';
return '[' + terms[0] + '; ' + terms.slice(1).join(', ') + ']';
}
function show(x, name){
const {terms, conv} = expand(x);
document.getElementById('cf').textContent =
(name?name+' = ':'') + fmtCF(terms);
const tb=document.getElementById('rows'); tb.innerHTML='';
conv.forEach(([h,k],i)=>{
const val=h/k, err=Math.abs(x-val);
const tr=document.createElement('tr');
const key=h+'/'+k;
if(FAMOUS.has(key)) tr.className='famous';
tr.innerHTML =
'<td>'+terms[i]+'</td>'+
'<td class="frac">'+key+'</td>'+
'<td>'+val.toFixed(8)+'</td>'+
'<td class="err">'+(err===0?'exact':err.toExponential(2))+'</td>';
tb.appendChild(tr);
});
console.log(name||x, '->', fmtCF(terms),
'| best convergent', conv[conv.length-1].join('/'));
}
document.querySelectorAll('.controls button').forEach(b=>{
b.addEventListener('click',()=>{
document.getElementById('num').value=b.dataset.x;
show(parseFloat(b.dataset.x), b.dataset.n);
});
});
document.getElementById('go').addEventListener('click',()=>{
const x=parseFloat(document.getElementById('num').value);
if(isFinite(x)) show(x, '');
else document.getElementById('cf').textContent='Enter a valid number.';
});
show(Math.PI, 'π');
Try π and watch 22/7 and then 355/113 pop out. Try the golden ratio (the hardest number to approximate) and see only 1s — its convergents are ratios of consecutive Fibonacci numbers, and they close in as slowly as any number possibly can. The key fact: no fraction with a smaller denominator ever beats one of these convergents.
Comments
Loading comments...