Bitwise operators work on numbers at the binary level (0s and 1s).
Though a bit advanced, they are super useful in fields like optimization, encryption, image processing, and hardware programming.
Operator | Symbol | What It Does |
|---|---|---|
AND |
| Sets each bit to 1 if both bits are 1 |
OR |
| Sets each bit to 1 if at least one of the bits is 1 |
XOR |
| Sets each bit to 1 if only one of the bits is 1 (not both) |
NOT |
| Inverts all bits (flips 0 to 1, and 1 to 0) |
Left Shift |
| Shifts bits to the left (adds zeros at the right) |
Right Shift |
| Shifts bits to the right (removes rightmost bits) |
& Bitwise AND
x = 5
x & 3 # Output: 1| Bitwise OR
x = 5
x | 3 # Output: 7^ Bitwise XOR
x = 5
x ^ 3 # Output: 6~ Bitwise NOT
x = 5
~x # Output: -6<< Left Shift
x = 3
x << 1 # Output: 6>> Right Shift
x = 8
x >> 1 # Output: 4<div class="infographic-pybits">
<style>
.infographic-pybits {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--mono-font: 'IBM Plex Mono', 'SFMono-Regular', Menlo, monospace;
--display-font: 'Fraunces', Georgia, serif;
--body-font: 'Inter', system-ui, sans-serif;
box-sizing: border-box;
max-width: 700px;
margin: 0 auto;
font-family: var(--body-font);
color: var(--ink);
background: var(--paper);
}
.infographic-pybits[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
}
.infographic-pybits *, .infographic-pybits *::before, .infographic-pybits *::after { box-sizing: border-box; }
.infographic-pybits .bw-wrap { padding: 0 clamp(1rem, 4vw, 2rem) 1.5rem; }
.infographic-pybits h1 {
font-family: var(--display-font); font-weight: 600;
font-size: clamp(1.6rem, 5vw, 2.2rem); text-align: center; margin: 1.5rem 0 0.25rem; letter-spacing: -0.01em;
}
.infographic-pybits .bw-sub { text-align: center; color: var(--ink-soft); font-size: 0.88rem; margin: 0 0 1.4rem; }
.infographic-pybits .bw-op-row { display: grid; grid-template-columns: repeat(6, 1fr); gap: 0.4rem; margin-bottom: 1.3rem; }
@media (max-width: 480px) { .infographic-pybits .bw-op-row { grid-template-columns: repeat(3, 1fr); } }
.infographic-pybits .bw-op-btn {
font: inherit; font-family: var(--mono-font); font-size: 1.05rem; font-weight: 700;
background: var(--paper-alt); border: 1.5px solid var(--line); color: var(--ink-soft);
padding: 0.5rem 0.2rem; cursor: pointer; border-radius: 5px; text-align: center;
}
.infographic-pybits .bw-op-btn.is-selected { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }
.infographic-pybits .bw-row { margin-bottom: 1rem; }
.infographic-pybits .bw-row-head { display: flex; align-items: baseline; justify-content: center; gap: 0.5rem; margin-bottom: 0.4rem; }
.infographic-pybits .bw-row-label { font-family: var(--display-font); font-size: 1rem; color: var(--ink); font-weight: 600; }
.infographic-pybits .bw-row-dec { font-family: var(--mono-font); font-size: 0.85rem; color: var(--accent); font-weight: 700; }
.infographic-pybits .bw-row-eq { font-family: var(--mono-font); font-size: 0.85rem; color: var(--ink-soft); }
.infographic-pybits .bw-dec-input {
font-family: var(--mono-font); font-size: 0.95rem; font-weight: 700; color: var(--accent);
width: 64px; text-align: center; padding: 0.2rem 0.3rem;
border: 1.5px solid var(--line); border-radius: 5px; background: var(--paper-alt);
}
.infographic-pybits .bw-dec-input:focus { outline: none; border-color: var(--accent); }
.infographic-pybits .bw-shift-input { width: 48px; font-size: 1.15rem; }
.infographic-pybits .bw-bits { display: flex; justify-content: center; gap: 0.28rem; flex-wrap: wrap; }
.infographic-pybits .bw-bit {
width: 30px; height: 34px; border: 1.5px solid var(--line); border-radius: 5px;
display: flex; align-items: center; justify-content: center;
font-family: var(--mono-font); font-weight: 700; font-size: 0.9rem;
background: var(--paper-alt); color: var(--ink-soft); cursor: pointer;
transition: background 0.15s, color 0.15s, border-color 0.15s, transform 0.1s;
user-select: none;
}
.infographic-pybits .bw-bit.is-on { background: var(--accent); border-color: var(--accent); color: #fff; }
.infographic-pybits .bw-bit:active { transform: scale(0.92); }
.infographic-pybits .bw-bit.readonly { cursor: default; }
.infographic-pybits .bw-bit.readonly:active { transform: none; }
.infographic-pybits .bw-shift-row { display: flex; align-items: center; justify-content: center; gap: 0.7rem; }
.infographic-pybits .bw-shift-btn {
width: 34px; height: 34px; border-radius: 50%; border: 1.5px solid var(--line);
background: var(--paper-alt); color: var(--ink); font-size: 1.1rem; font-weight: 700; cursor: pointer;
}
.infographic-pybits .bw-arrow { text-align: center; color: var(--accent); font-size: 1.3rem; margin: 0.6rem 0; }
.infographic-pybits .bw-result-dec {
text-align: center; font-family: var(--mono-font); font-size: 1.5rem; font-weight: 700; color: var(--accent);
margin-top: 0.5rem;
}
.infographic-pybits .bw-caption { text-align: center; font-size: 0.8rem; color: var(--ink-soft); margin-top: 0.4rem; }
.infographic-pybits .bw-note { text-align: center; font-size: 0.74rem; color: var(--ink-soft); font-style: italic; margin-top: 0.3rem; }
@media (prefers-reduced-motion: reduce) {
.infographic-pybits *, .infographic-pybits *::before, .infographic-pybits *::after {
animation-duration: 0.001ms !important; transition-duration: 0.001ms !important;
}
}
</style>
<div class="bw-wrap">
<h1>Bitwise Operators</h1>
<p class="bw-sub">Tap the bits. Watch the result rebuild.</p>
<div class="bw-op-row">
<button class="bw-op-btn is-selected" data-op="and">&</button>
<button class="bw-op-btn" data-op="or">|</button>
<button class="bw-op-btn" data-op="xor">^</button>
<button class="bw-op-btn" data-op="not">~</button>
<button class="bw-op-btn" data-op="lshift"><<</button>
<button class="bw-op-btn" data-op="rshift">>></button>
</div>
<div class="bw-row">
<div class="bw-row-head">
<span class="bw-row-label">x</span>
<span class="bw-row-eq">=</span>
<input class="bw-dec-input" id="bwXDec" type="text" value="5" inputmode="numeric" />
</div>
<div class="bw-bits" id="bwXBits"></div>
</div>
<div class="bw-row" id="bwYRow">
<div class="bw-row-head">
<span class="bw-row-label">y</span>
<span class="bw-row-eq">=</span>
<input class="bw-dec-input" id="bwYDec" type="text" value="3" inputmode="numeric" />
</div>
<div class="bw-bits" id="bwYBits"></div>
</div>
<div class="bw-row" id="bwShiftRow" style="display:none;">
<div class="bw-row-head"><span class="bw-row-label">shift by</span></div>
<div class="bw-shift-row">
<button class="bw-shift-btn" id="bwShiftMinus">−</button>
<input class="bw-dec-input bw-shift-input" id="bwShiftVal" type="text" value="1" inputmode="numeric" />
<button class="bw-shift-btn" id="bwShiftPlus">+</button>
</div>
</div>
<div class="bw-arrow">↓</div>
<div class="bw-row">
<div class="bw-row-head">
<span class="bw-row-label">result</span>
</div>
<div class="bw-bits" id="bwResultBits"></div>
</div>
<div class="bw-result-dec" id="bwResultDec">= 1</div>
<p class="bw-caption" id="bwCaption"></p>
<p class="bw-note" id="bwNote" style="display:none;"></p>
</div>
<script>
(function () {
var root = document.currentScript.closest('.infographic-pybits')
|| document.querySelector('.infographic-pybits');
var bodyAttr = document.body.getAttribute('data-darkmode');
var dark;
if (bodyAttr === 'true') { dark = true; }
else if (bodyAttr === 'false') { dark = false; }
else {
var match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) root.setAttribute('data-theme', 'dark');
var opBtns = root.querySelectorAll('.bw-op-btn');
var xBitsEl = root.querySelector('#bwXBits');
var yBitsEl = root.querySelector('#bwYBits');
var xDecEl = root.querySelector('#bwXDec');
var yDecEl = root.querySelector('#bwYDec');
var yRow = root.querySelector('#bwYRow');
var shiftRow = root.querySelector('#bwShiftRow');
var shiftValEl = root.querySelector('#bwShiftVal');
var shiftMinus = root.querySelector('#bwShiftMinus');
var shiftPlus = root.querySelector('#bwShiftPlus');
var resultBitsEl = root.querySelector('#bwResultBits');
var resultDecEl = root.querySelector('#bwResultDec');
var caption = root.querySelector('#bwCaption');
var noteEl = root.querySelector('#bwNote');
var WIDTH = 8;
var xBits = [0, 0, 0, 0, 0, 1, 0, 1]; // 5
var yBits = [0, 0, 0, 0, 0, 0, 1, 1]; // 3
var shiftAmount = 1;
var currentOp = 'and';
var captions = {
and: 'A result bit is 1 only where both x and y have 1.',
or: 'A result bit is 1 where x or y (or both) has 1.',
xor: 'A result bit is 1 where x and y differ.',
not: 'Every bit flips — but Python integers keep going forever.',
lshift: 'Bits move left, zeros fill in — same as ×2 per step.',
rshift: 'Bits move right — same as ÷2 per step, rounded down.'
};
function bitsToDec(bits) {
var v = 0;
for (var i = 0; i < bits.length; i++) v = v * 2 + bits[i];
return v;
}
function decToBits(v, width) {
var s = (v >>> 0).toString(2);
while (s.length < width) s = '0' + s;
if (s.length > width) s = s.slice(s.length - width);
var arr = [];
for (var i = 0; i < s.length; i++) arr.push(Number(s[i]));
return arr;
}
function renderBitRow(container, bits, toggleable, onToggle) {
container.innerHTML = '';
bits.forEach(function (bit, idx) {
var cell = document.createElement(toggleable ? 'button' : 'div');
cell.className = 'bw-bit' + (bit ? ' is-on' : '') + (toggleable ? '' : ' readonly');
cell.textContent = bit;
if (toggleable) {
cell.addEventListener('click', function () { onToggle(idx); });
}
container.appendChild(cell);
});
}
function recompute() {
var x = bitsToDec(xBits);
var y = bitsToDec(yBits);
xDecEl.value = String(x);
yDecEl.value = String(y);
renderBitRow(xBitsEl, xBits, true, function (idx) {
xBits[idx] = xBits[idx] ? 0 : 1;
recompute();
});
noteEl.style.display = 'none';
if (currentOp === 'not') {
yRow.style.display = 'none';
shiftRow.style.display = 'none';
var flipped = xBits.map(function (b) { return b ? 0 : 1; });
renderBitRow(resultBitsEl, flipped, false);
var realResult = -(x + 1);
resultDecEl.textContent = '= ' + realResult;
caption.textContent = captions.not;
noteEl.style.display = 'block';
noteEl.textContent = 'Shown: 8 bits flipped for x=' + x + '. Actual Python value: ~x = -(x+1) = ' + realResult + '.';
return;
}
if (currentOp === 'lshift' || currentOp === 'rshift') {
yRow.style.display = 'none';
shiftRow.style.display = 'block';
shiftValEl.value = String(shiftAmount);
var result = currentOp === 'lshift' ? (x << shiftAmount) : (x >> shiftAmount);
var width = Math.max(WIDTH, result === 0 ? 1 : result.toString(2).length);
width = Math.min(width, 16);
renderBitRow(resultBitsEl, decToBits(result, width), false);
resultDecEl.textContent = '= ' + result;
caption.textContent = captions[currentOp];
return;
}
// and / or / xor
yRow.style.display = 'block';
shiftRow.style.display = 'none';
renderBitRow(yBitsEl, yBits, true, function (idx) {
yBits[idx] = yBits[idx] ? 0 : 1;
recompute();
});
var res;
if (currentOp === 'and') res = x & y;
else if (currentOp === 'or') res = x | y;
else res = x ^ y;
renderBitRow(resultBitsEl, decToBits(res, WIDTH), false);
resultDecEl.textContent = '= ' + res;
caption.textContent = captions[currentOp];
}
opBtns.forEach(function (btn) {
btn.addEventListener('click', function () {
opBtns.forEach(function (b) { b.classList.toggle('is-selected', b === btn); });
currentOp = btn.dataset.op;
recompute();
});
});
shiftMinus.addEventListener('click', function () {
shiftAmount = Math.max(0, shiftAmount - 1);
recompute();
});
shiftPlus.addEventListener('click', function () {
shiftAmount = Math.min(7, shiftAmount + 1);
recompute();
});
function clamp(v, min, max) { return Math.max(min, Math.min(max, v)); }
xDecEl.addEventListener('input', function () {
var v = parseInt(xDecEl.value, 10);
if (isNaN(v)) return;
xBits = decToBits(clamp(v, 0, 255), WIDTH);
recompute();
});
yDecEl.addEventListener('input', function () {
var v = parseInt(yDecEl.value, 10);
if (isNaN(v)) return;
yBits = decToBits(clamp(v, 0, 255), WIDTH);
recompute();
});
shiftValEl.addEventListener('input', function () {
var v = parseInt(shiftValEl.value, 10);
if (isNaN(v)) return;
shiftAmount = clamp(v, 0, 7);
recompute();
});
recompute();
})();
</script>
</div>