binary to decimal
This commit is contained in:
459
binary-to-decimal-converter.html
Normal file
459
binary-to-decimal-converter.html
Normal file
@@ -0,0 +1,459 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Binary to Decimal Converter - Form 1</title>
|
||||
<style>
|
||||
:root {
|
||||
--primary: #4527a0;
|
||||
--accent: #00838f;
|
||||
--soft: #ede7f6;
|
||||
--soft-alt: #d1c4e9;
|
||||
--good: #2e7d32;
|
||||
--good-soft: #e8f5e9;
|
||||
--warn: #c62828;
|
||||
--warn-soft: #ffebee;
|
||||
--ink: #1a1a1a;
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
line-height: 1.5;
|
||||
max-width: 1100px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background: #f5f3fa;
|
||||
color: var(--ink);
|
||||
}
|
||||
.app {
|
||||
background: #fff;
|
||||
padding: 28px 34px;
|
||||
border: 2px solid var(--primary);
|
||||
box-shadow: 0 2px 10px rgba(69, 39, 160, 0.08);
|
||||
}
|
||||
.header {
|
||||
text-align: center;
|
||||
border-bottom: 3px solid var(--primary);
|
||||
padding-bottom: 12px;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
.header h1 { margin: 0; font-size: 1.6em; color: var(--primary); }
|
||||
.header h2 { margin: 4px 0 0; font-size: 1em; color: var(--accent); font-weight: normal; }
|
||||
h3 {
|
||||
border-bottom: 2px solid var(--primary);
|
||||
padding: 6px 0;
|
||||
margin: 22px 0 10px 0;
|
||||
font-size: 1.1em;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
color: var(--primary);
|
||||
}
|
||||
.input-row {
|
||||
display: flex;
|
||||
gap: 14px;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.input-row label {
|
||||
font-weight: bold;
|
||||
color: var(--primary);
|
||||
font-size: 1em;
|
||||
}
|
||||
#binaryInput {
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 1.6em;
|
||||
padding: 6px 10px;
|
||||
border: 2px solid var(--primary);
|
||||
color: var(--primary);
|
||||
letter-spacing: 4px;
|
||||
width: 220px;
|
||||
text-align: center;
|
||||
background: #fff;
|
||||
}
|
||||
#binaryInput:focus {
|
||||
outline: 2px solid var(--accent);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
button {
|
||||
font-family: inherit;
|
||||
font-size: 0.95em;
|
||||
padding: 8px 14px;
|
||||
border: 1.5px solid var(--accent);
|
||||
background: #fff;
|
||||
color: var(--accent);
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.4px;
|
||||
}
|
||||
button:hover { background: var(--soft); color: var(--primary); border-color: var(--primary); }
|
||||
button.primary { background: var(--primary); color: #fff; border-color: var(--primary); }
|
||||
button.primary:hover { background: #311b92; color: #fff; }
|
||||
button.warn { color: var(--warn); border-color: var(--warn); }
|
||||
button.warn:hover { background: var(--warn-soft); color: var(--warn); }
|
||||
.preset-row {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
margin: 6px 0 12px;
|
||||
}
|
||||
.preset-row button {
|
||||
font-family: 'Courier New', monospace;
|
||||
letter-spacing: 2px;
|
||||
padding: 4px 10px;
|
||||
font-size: 1em;
|
||||
text-transform: none;
|
||||
}
|
||||
.chart-wrapper {
|
||||
border: 2px solid var(--primary);
|
||||
padding: 14px;
|
||||
margin: 12px 0;
|
||||
background: var(--soft);
|
||||
overflow-x: auto;
|
||||
}
|
||||
.chart {
|
||||
margin: 0 auto;
|
||||
border-collapse: collapse;
|
||||
font-family: 'Courier New', monospace;
|
||||
}
|
||||
.chart td {
|
||||
border: 1.5px solid var(--primary);
|
||||
padding: 10px 18px;
|
||||
text-align: center;
|
||||
background: #fff;
|
||||
min-width: 64px;
|
||||
}
|
||||
.chart .row-power { background: var(--soft); color: var(--primary); font-weight: bold; font-size: 1em; }
|
||||
.chart .row-value { background: #fff; color: var(--primary); font-weight: bold; font-size: 1.15em; }
|
||||
.chart .row-digit { background: #fff; font-size: 1.6em; font-weight: bold; }
|
||||
.chart .row-contrib { background: #fafbfc; color: var(--accent); font-weight: bold; font-size: 1.05em; }
|
||||
.chart .row-digit.is-one { background: var(--good-soft); color: var(--good); }
|
||||
.chart .row-contrib.is-one { background: var(--good-soft); color: var(--good); }
|
||||
.chart .row-digit.is-zero { color: #888; }
|
||||
.chart .row-contrib.is-zero { color: #888; }
|
||||
.working-line {
|
||||
text-align: center;
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 1.2em;
|
||||
margin: 10px 0;
|
||||
color: var(--primary);
|
||||
font-weight: bold;
|
||||
}
|
||||
.answer-banner {
|
||||
border: 2px solid var(--good);
|
||||
background: var(--good-soft);
|
||||
color: var(--good);
|
||||
padding: 14px 18px;
|
||||
text-align: center;
|
||||
font-size: 1.4em;
|
||||
font-weight: bold;
|
||||
margin: 14px 0 6px;
|
||||
font-family: 'Courier New', monospace;
|
||||
}
|
||||
.answer-banner.hidden {
|
||||
background: var(--soft);
|
||||
color: var(--primary);
|
||||
border-color: var(--primary);
|
||||
}
|
||||
.error-banner {
|
||||
border: 2px solid var(--warn);
|
||||
background: var(--warn-soft);
|
||||
color: var(--warn);
|
||||
padding: 10px 14px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
margin: 12px 0;
|
||||
}
|
||||
.controls-row {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
margin: 6px 0 0;
|
||||
}
|
||||
.footer-note {
|
||||
margin-top: 18px;
|
||||
padding: 8px 12px;
|
||||
border-left: 4px solid var(--accent);
|
||||
background: var(--soft);
|
||||
color: var(--primary);
|
||||
font-size: 0.92em;
|
||||
}
|
||||
@media print {
|
||||
body { background: #fff !important; color: #000 !important; }
|
||||
.app { border: 1.5px solid #000 !important; box-shadow: none !important; }
|
||||
*, *::before, *::after {
|
||||
background: #fff !important;
|
||||
background-color: #fff !important;
|
||||
color: #000 !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
.header, h3, .chart-wrapper, .chart td, .answer-banner, .error-banner, button, .footer-note {
|
||||
border-color: #000 !important;
|
||||
}
|
||||
button { display: none !important; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="app">
|
||||
<div class="header">
|
||||
<h1>BINARY → DECIMAL CONVERTER</h1>
|
||||
<h2>Form 1 - Lesson 30 - Same shape, different base</h2>
|
||||
</div>
|
||||
|
||||
<h3>Type a Binary Number</h3>
|
||||
<div class="input-row">
|
||||
<label for="binaryInput">Binary:</label>
|
||||
<input id="binaryInput" type="text" maxlength="8" autocomplete="off" spellcheck="false" placeholder="e.g. 1011">
|
||||
<button class="primary" id="convertBtn">Convert</button>
|
||||
<button id="clearBtn">Clear</button>
|
||||
<button id="randomBtn">Random</button>
|
||||
</div>
|
||||
|
||||
<div class="preset-row">
|
||||
<button data-preset="101">101</button>
|
||||
<button data-preset="1011">1011</button>
|
||||
<button data-preset="1101">1101</button>
|
||||
<button data-preset="10101">10101</button>
|
||||
<button data-preset="11000">11000</button>
|
||||
<button data-preset="11111">11111</button>
|
||||
<button data-preset="100000">100000</button>
|
||||
<button data-preset="110010">110010</button>
|
||||
</div>
|
||||
|
||||
<div id="errorMsg" class="error-banner" style="display: none;"></div>
|
||||
|
||||
<h3>Place Value Chart (powers of 2)</h3>
|
||||
<div class="chart-wrapper">
|
||||
<table class="chart">
|
||||
<tbody id="chartBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="workingLine" class="working-line"></div>
|
||||
|
||||
<div id="answerBanner" class="answer-banner hidden">Type a binary number above and press Convert.</div>
|
||||
|
||||
<div class="controls-row">
|
||||
<button id="revealBtn">Hide Answer</button>
|
||||
<button id="hideChartBtn">Hide Chart</button>
|
||||
</div>
|
||||
|
||||
<div class="footer-note">
|
||||
<strong>For students:</strong> solve on paper <em>first</em> using the chart in your worksheet. Type the binary number here only to <em>check</em>. The lesson is in the chart, not the click.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
const input = document.getElementById('binaryInput');
|
||||
const convertBtn = document.getElementById('convertBtn');
|
||||
const clearBtn = document.getElementById('clearBtn');
|
||||
const randomBtn = document.getElementById('randomBtn');
|
||||
const revealBtn = document.getElementById('revealBtn');
|
||||
const hideChartBtn = document.getElementById('hideChartBtn');
|
||||
const chartBody = document.getElementById('chartBody');
|
||||
const chartWrapper = document.querySelector('.chart-wrapper');
|
||||
const workingLine = document.getElementById('workingLine');
|
||||
const answerBanner = document.getElementById('answerBanner');
|
||||
const errorMsg = document.getElementById('errorMsg');
|
||||
|
||||
let answerHidden = false;
|
||||
let chartHidden = false;
|
||||
|
||||
function clearError() {
|
||||
errorMsg.style.display = 'none';
|
||||
errorMsg.textContent = '';
|
||||
}
|
||||
|
||||
function showError(msg) {
|
||||
errorMsg.textContent = msg;
|
||||
errorMsg.style.display = 'block';
|
||||
}
|
||||
|
||||
function powerOfTwo(n) {
|
||||
let v = 1;
|
||||
for (let i = 0; i < n; i++) v *= 2;
|
||||
return v;
|
||||
}
|
||||
|
||||
function buildChartFor(binaryStr) {
|
||||
const n = binaryStr.length;
|
||||
const powerRow = document.createElement('tr');
|
||||
const valueRow = document.createElement('tr');
|
||||
const digitRow = document.createElement('tr');
|
||||
const contribRow = document.createElement('tr');
|
||||
|
||||
powerRow.className = '';
|
||||
for (let i = 0; i < n; i++) {
|
||||
const exponent = n - 1 - i;
|
||||
const digit = binaryStr[i];
|
||||
const placeVal = powerOfTwo(exponent);
|
||||
const contrib = parseInt(digit, 10) * placeVal;
|
||||
|
||||
const pTd = document.createElement('td');
|
||||
pTd.className = 'row-power';
|
||||
pTd.innerHTML = '2<sup>' + exponent + '</sup>';
|
||||
powerRow.appendChild(pTd);
|
||||
|
||||
const vTd = document.createElement('td');
|
||||
vTd.className = 'row-value';
|
||||
vTd.textContent = placeVal;
|
||||
valueRow.appendChild(vTd);
|
||||
|
||||
const dTd = document.createElement('td');
|
||||
dTd.className = 'row-digit ' + (digit === '1' ? 'is-one' : 'is-zero');
|
||||
dTd.textContent = digit;
|
||||
digitRow.appendChild(dTd);
|
||||
|
||||
const cTd = document.createElement('td');
|
||||
cTd.className = 'row-contrib ' + (digit === '1' ? 'is-one' : 'is-zero');
|
||||
cTd.textContent = contrib;
|
||||
contribRow.appendChild(cTd);
|
||||
}
|
||||
|
||||
chartBody.innerHTML = '';
|
||||
chartBody.appendChild(powerRow);
|
||||
chartBody.appendChild(valueRow);
|
||||
chartBody.appendChild(digitRow);
|
||||
chartBody.appendChild(contribRow);
|
||||
}
|
||||
|
||||
function renderEmpty() {
|
||||
chartBody.innerHTML = '';
|
||||
const powerRow = document.createElement('tr');
|
||||
const valueRow = document.createElement('tr');
|
||||
const digitRow = document.createElement('tr');
|
||||
const contribRow = document.createElement('tr');
|
||||
for (let exp = 5; exp >= 0; exp--) {
|
||||
const placeVal = powerOfTwo(exp);
|
||||
const pTd = document.createElement('td');
|
||||
pTd.className = 'row-power';
|
||||
pTd.innerHTML = '2<sup>' + exp + '</sup>';
|
||||
powerRow.appendChild(pTd);
|
||||
const vTd = document.createElement('td');
|
||||
vTd.className = 'row-value';
|
||||
vTd.textContent = placeVal;
|
||||
valueRow.appendChild(vTd);
|
||||
const dTd = document.createElement('td');
|
||||
dTd.className = 'row-digit is-zero';
|
||||
dTd.textContent = '_';
|
||||
digitRow.appendChild(dTd);
|
||||
const cTd = document.createElement('td');
|
||||
cTd.className = 'row-contrib is-zero';
|
||||
cTd.textContent = '_';
|
||||
contribRow.appendChild(cTd);
|
||||
}
|
||||
chartBody.appendChild(powerRow);
|
||||
chartBody.appendChild(valueRow);
|
||||
chartBody.appendChild(digitRow);
|
||||
chartBody.appendChild(contribRow);
|
||||
workingLine.textContent = '';
|
||||
setBanner('Type a binary number above and press Convert.', true);
|
||||
}
|
||||
|
||||
function setBanner(text, hidden) {
|
||||
answerBanner.textContent = text;
|
||||
if (hidden) answerBanner.classList.add('hidden');
|
||||
else answerBanner.classList.remove('hidden');
|
||||
}
|
||||
|
||||
function convert() {
|
||||
clearError();
|
||||
const raw = input.value.trim();
|
||||
if (raw.length === 0) {
|
||||
showError('Type a binary number first (only 0s and 1s).');
|
||||
renderEmpty();
|
||||
return;
|
||||
}
|
||||
if (!/^[01]+$/.test(raw)) {
|
||||
showError('Binary numbers use only 0 and 1. Found another digit.');
|
||||
renderEmpty();
|
||||
return;
|
||||
}
|
||||
if (raw.length > 8) {
|
||||
showError('Keep it to 8 digits or fewer for this lesson.');
|
||||
return;
|
||||
}
|
||||
|
||||
buildChartFor(raw);
|
||||
|
||||
const n = raw.length;
|
||||
let total = 0;
|
||||
const ones = [];
|
||||
const allTerms = [];
|
||||
for (let i = 0; i < n; i++) {
|
||||
const exponent = n - 1 - i;
|
||||
const digit = parseInt(raw[i], 10);
|
||||
const placeVal = powerOfTwo(exponent);
|
||||
allTerms.push(digit + '×' + placeVal);
|
||||
if (digit === 1) {
|
||||
ones.push(placeVal);
|
||||
total += placeVal;
|
||||
}
|
||||
}
|
||||
const fullExpansion = allTerms.join(' + ');
|
||||
const onesOnly = ones.length > 0 ? ones.join(' + ') + ' = ' + total : '0';
|
||||
workingLine.innerHTML = fullExpansion + '<br>= ' + onesOnly;
|
||||
|
||||
if (answerHidden) {
|
||||
setBanner(raw + '₂ = ? (press Show Answer)', true);
|
||||
} else {
|
||||
setBanner(raw + '₂ = ' + total + ' in denary', false);
|
||||
}
|
||||
}
|
||||
|
||||
input.addEventListener('input', function() {
|
||||
input.value = input.value.replace(/[^01]/g, '');
|
||||
});
|
||||
input.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Enter') convert();
|
||||
});
|
||||
|
||||
convertBtn.addEventListener('click', convert);
|
||||
|
||||
clearBtn.addEventListener('click', function() {
|
||||
input.value = '';
|
||||
clearError();
|
||||
renderEmpty();
|
||||
input.focus();
|
||||
});
|
||||
|
||||
randomBtn.addEventListener('click', function() {
|
||||
const len = 3 + Math.floor(Math.random() * 4);
|
||||
let s = '1';
|
||||
for (let i = 1; i < len; i++) {
|
||||
s += (Math.random() < 0.5 ? '0' : '1');
|
||||
}
|
||||
input.value = s;
|
||||
convert();
|
||||
});
|
||||
|
||||
document.querySelectorAll('.preset-row button[data-preset]').forEach(function(btn) {
|
||||
btn.addEventListener('click', function() {
|
||||
input.value = btn.getAttribute('data-preset');
|
||||
convert();
|
||||
});
|
||||
});
|
||||
|
||||
revealBtn.addEventListener('click', function() {
|
||||
answerHidden = !answerHidden;
|
||||
revealBtn.textContent = answerHidden ? 'Show Answer' : 'Hide Answer';
|
||||
if (input.value.trim().length > 0) convert();
|
||||
});
|
||||
|
||||
hideChartBtn.addEventListener('click', function() {
|
||||
chartHidden = !chartHidden;
|
||||
chartWrapper.style.display = chartHidden ? 'none' : 'block';
|
||||
hideChartBtn.textContent = chartHidden ? 'Show Chart' : 'Hide Chart';
|
||||
});
|
||||
|
||||
renderEmpty();
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user