ergod
Built with Ergod

Fibonacci Calculator

Shared 2026-09-17 · 31 views
About this creation

A creation shared by its maker. The page below runs in a sandbox that cannot read anything of yours or talk to any server. Read the source before you run it anywhere else.

Interactive page
Open full page
Show source
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Fibonacci Calculator</title>
<style>
  * { margin: 0; padding: 0; box-sizing: border-box; }
  body {
    font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
    background: #0d1117; color: #e6edf3; min-height: 100vh;
    display: flex; flex-direction: column; align-items: center;
    padding: 2.5rem 1.5rem; gap: 2rem;
  }
  h1 {
    font-size: clamp(1.8rem, 5vw, 2.8rem); font-weight: 900; letter-spacing: -1px;
    background: linear-gradient(90deg, #ff7b72, #d2a8ff, #79c0ff);
    -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
  }
  .sub { color: #8b949e; margin-top: -.5rem; }
  .tabs { display: flex; gap: .5rem; background: #161b22; padding: .4rem; border-radius: 12px; flex-wrap: wrap; }
  .tab {
    padding: .6rem 1.2rem; border-radius: 8px; cursor: pointer; font-weight: 600;
    color: #8b949e; border: none; background: transparent; font-size: .95rem; transition: .15s;
  }
  .tab.active { background: #21262d; color: #e6edf3; }
  .panel { width: 100%; max-width: 640px; background: #161b22; border: 1px solid #30363d;
    border-radius: 16px; padding: 2rem; display: none; }
  .panel.active { display: block; }
  label { display: block; font-size: .85rem; color: #8b949e; margin-bottom: .4rem; }
  input {
    width: 100%; background: #0d1117; border: 1px solid #30363d; color: #e6edf3;
    padding: .75rem .9rem; border-radius: 10px; font-size: 1.1rem; font-family: inherit;
  }
  input:focus { outline: none; border-color: #79c0ff; box-shadow: 0 0 0 3px rgba(121,192,255,.18); }
  .row { display: flex; gap: 1rem; align-items: flex-end; margin-bottom: 1.2rem; flex-wrap: wrap; }
  .row > div { flex: 1; min-width: 140px; }
  button.calc {
    background: linear-gradient(90deg, #ff7b72, #d2a8ff); color: #0d1117; border: none;
    padding: .75rem 1.8rem; border-radius: 10px; font-weight: 800; font-size: 1rem; cursor: pointer;
    transition: transform .12s;
  }
  button.calc:hover { transform: translateY(-2px); }
  .result {
    margin-top: 1.4rem; padding: 1.2rem 1.4rem; background: #0d1117; border-radius: 12px;
    border: 1px solid #30363d; font-size: 1.05rem; line-height: 1.7;
  }
  .result .big { font-size: 1.8rem; font-weight: 900; color: #79c0ff; word-break: break-all; }
  .result .label { color: #8b949e; font-size: .85rem; text-transform: uppercase; letter-spacing: .08em; }
  .seq { font-family: 'SF Mono', ui-monospace, monospace; font-size: .9rem; line-height: 1.9;
    word-break: break-all; color: #d2a8ff; }
  .err { color: #ff7b72; font-weight: 600; }
  .spiral { display: flex; justify-content: center; margin-top: 1rem; }
  footer { color: #484f58; font-size: .8rem; text-align: center; }
  code { background: #21262d; padding: .15rem .4rem; border-radius: 5px; font-size: .85em; }
</style>
</head>
<body>
  <h1>🔢 Fibonacci Calculator</h1>
  <p class="sub">The sequence where each number is the sum of the two before it: 0, 1, 1, 2, 3, 5, 8…</p>

  <div class="tabs">
    <button class="tab active" data-tab="nth">Nth Term</button>
    <button class="tab" data-tab="seq">Generate Sequence</button>
    <button class="tab" data-tab="check">Is It Fibonacci?</button>
  </div>

  <!-- NTH -->
  <div class="panel active" id="nth">
    <label for="n-input">Which term? (n = position, starting at 0)</label>
    <input id="n-input" type="number" min="0" max="2000" placeholder="e.g. 20" value="20">
    <div class="row" style="margin-top:1rem;">
      <button class="calc" onclick="computeNth()">Compute F(n)</button>
    </div>
    <div class="result" id="nth-result"><span class="label">Result</span><div class="big">—</div></div>
  </div>

  <!-- SEQUENCE -->
  <div class="panel" id="seq">
    <div class="row">
      <div>
        <label for="seq-from">From (n)</label>
        <input id="seq-from" type="number" min="0" max="2000" value="0">
      </div>
      <div>
        <label for="seq-to">To (n)</label>
        <input id="seq-to" type="number" min="0" max="2000" value="15">
      </div>
    </div>
    <button class="calc" onclick="computeSeq()">Generate</button>
    <div class="result" id="seq-result"><span class="label">Sequence</span><div class="seq">—</div></div>
  </div>

  <!-- CHECK -->
  <div class="panel" id="check">
    <label for="check-input">Enter a number to test</label>
    <input id="check-input" type="number" placeholder="e.g. 34" value="34">
    <div class="row" style="margin-top:1rem;">
      <button class="calc" onclick="checkFib()">Check</button>
    </div>
    <div class="result" id="check-result"><span class="label">Verdict</span><div class="big">—</div></div>
  </div>

  <footer>Built for nahstalgic · no external dependencies</footer>

<script>
  function tabSwitch() {
    document.querySelectorAll('.tab').forEach(t => {
      t.onclick = () => {
        document.querySelectorAll('.tab').forEach(x => x.classList.remove('active'));
        document.querySelectorAll('.panel').forEach(x => x.classList.remove('active'));
        t.classList.add('active');
        document.getElementById(t.dataset.tab).classList.add('active');
      };
    });
  }
  tabSwitch();

  // Big-int safe nth Fibonacci via fast doubling (handles huge n)
  function fib(n) {
    if (n < 0) return null;
    let a = 0n, b = 1n; // F(0), F(1)
    n = BigInt(n);
    for (let bit = n.toString(2); bit.length; bit = bit.slice(1)) {
      const c = a * (2n * b - a);
      const d = a * a + b * b;
      if (bit[0] === '1') { a = d; b = c + d; }
      else { a = c; b = d; }
    }
    return a;
  }

  function computeNth() {
    const el = document.getElementById('n-input');
    const out = document.getElementById('nth-result');
    const n = parseInt(el.value);
    if (isNaN(n) || n < 0) { out.innerHTML = '<span class="err">Enter a non-negative integer.</span>'; return; }
    if (n > 2000) { out.innerHTML = '<span class="err">Keep n ≤ 2000 (that\'s already ~418 digits!).</span>'; return; }
    const val = fib(n);
    out.innerHTML = `<span class="label">F(${n})</span><div class="big">${val}</div><div style="color:#8b949e;margin-top:.4rem">${val.toString().length} digits</div>`;
  }

  function computeSeq() {
    const f = parseInt(document.getElementById('seq-from').value);
    const t = parseInt(document.getElementById('seq-to').value);
    const out = document.getElementById('seq-result');
    if (isNaN(f) || isNaN(t) || f < 0 || t < f) { out.innerHTML = '<span class="err">Enter valid from ≤ to, both ≥ 0.</span>'; return; }
    if (t - f > 200) { out.innerHTML = '<span class="err">Max 200 terms per view.</span>'; return; }
    const terms = [];
    for (let i = f; i <= t; i++) terms.push(`F(${i})=${fib(i)}`);
    out.innerHTML = `<span class="label">Terms F(${f}) … F(${t})</span><div class="seq">${terms.join('<br>')}</div>`;
  }

  function isPerfectSquare(x) {
    if (x < 0n) return false;
    if (x < 2n) return true;
    let lo = 0n, hi = x;
    while (lo <= hi) {
      const mid = (lo + hi) / 2n;
      const sq = mid * mid;
      if (sq === x) return true;
      if (sq < x) lo = mid + 1n; else hi = mid - 1n;
    }
    return false;
  }

  function checkFib() {
    const el = document.getElementById('check-input');
    const out = document.getElementById('check-result');
    const v = el.value.trim();
    if (!/^\d+$/.test(v)) { out.innerHTML = '<span class="err">Enter a non-negative integer.</span>'; return; }
    const n = BigInt(v);
    // n is Fibonacci iff 5n^2 + 4 or 5n^2 - 4 is a perfect square
    const t1 = 5n * n * n + 4n;
    const t2 = 5n * n * n - 4n;
    if (isPerfectSquare(t1) || isPerfectSquare(t2)) {
      out.innerHTML = `<span class="label">${n} is a Fibonacci number</span><div class="big">✓ YES</div>`;
    } else {
      out.innerHTML = `<span class="label">${n} is NOT Fibonacci</span><div class="big">✗ NO</div>`;
    }
  }

  computeNth(); // demo on load
</script>
</body>
</html>