tanszek:oktatas:techcomm:encoding_integers
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| tanszek:oktatas:techcomm:encoding_integers [2026/10/12 18:25] – knehez | tanszek:oktatas:techcomm:encoding_integers [2026/10/12 18:32] (current) – knehez | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ==== Integer representations ==== | + | ===== Integer representations |
| Computers store data as bits. Each bit can have one of two values: 0 or 1. A byte consists of 8 bits, so it has 2< | Computers store data as bits. Each bit can have one of two values: 0 or 1. A byte consists of 8 bits, so it has 2< | ||
| Line 11: | Line 11: | ||
| === Unsigned integers === | === Unsigned integers === | ||
| - | In ordinary decimal notation, | + | In ordinary decimal notation, |
| In binary notation, the weights are powers of two: | In binary notation, the weights are powers of two: | ||
| Line 148: | Line 148: | ||
| </ | </ | ||
| - | The expected result is +2. To obtain | + | The expected result is +2. To get it, an arithmetic procedure for sign-magnitude numbers must account for the signs and subtract the magnitudes. |
| === Two's complement representation === | === Two's complement representation === | ||
| Line 154: | Line 154: | ||
| A widely used alternative for signed integers is **two' | A widely used alternative for signed integers is **two' | ||
| - | Its main advantage is that positive and negative integers | + | Its main advantage is that you can add positive and negative integers using the same binary addition procedure as with unsigned integers. |
| Let us first see what bit pattern would make this possible. | Let us first see what bit pattern would make this possible. | ||
| Line 216: | Line 216: | ||
| | Weight | **−128** | 64 | 32 | 16 | 8 | 4 | 2 | 1 | | | Weight | **−128** | 64 | 32 | 16 | 8 | 4 | 2 | 1 | | ||
| - | Only the weight of the leftmost bit differs from the unsigned case. | + | Only the leftmost bit's weight |
| Consequently: | Consequently: | ||
| Line 278: | Line 278: | ||
| The result is correct. | The result is correct. | ||
| - | The carry-out is discarded in this fixed-width calculation. **A carry-out does not, by itself, indicate signed overflow.** | + | This fixed-width calculation |
| Two's complement makes addition convenient, but the result must still fit in the available signed range. | Two's complement makes addition convenient, but the result must still fit in the available signed range. | ||
| Line 308: | Line 308: | ||
| **Carry-out and signed overflow describe different conditions.** | **Carry-out and signed overflow describe different conditions.** | ||
| - | These examples describe fixed-width binary arithmetic. Programming languages may handle out-of-range calculations differently, | + | These examples describe fixed-width binary arithmetic. Programming languages may handle out-of-range calculations differently, |
| === Check your understanding === | === Check your understanding === | ||
| Line 327: | Line 327: | ||
| - No. The greatest positive value is +127. The unsigned pattern for 156, 10011100, represents −100 when interpreted as two's complement. | - No. The greatest positive value is +127. The unsigned pattern for 156, 10011100, represents −100 when interpreted as two's complement. | ||
| - The resulting pattern is **10000000**, | - The resulting pattern is **10000000**, | ||
| + | |||
| + | < | ||
| + | <div class=" | ||
| + | < | ||
| + | .tc-lab { | ||
| + | max-width: 900px; | ||
| + | margin: 24px auto; | ||
| + | padding: 24px; | ||
| + | border: 1px solid #cbd5e1; | ||
| + | border-radius: | ||
| + | background: #f8fafc; | ||
| + | color: #172033; | ||
| + | font: 16px/1.6 system-ui, sans-serif; | ||
| + | } | ||
| + | .tc-lab * { box-sizing: border-box; } | ||
| + | .tc-lab h2, .tc-lab h3 { color: #172033; margin: 0 0 12px; } | ||
| + | .tc-lab p { margin: 10px 0; } | ||
| + | .tc-lab button, .tc-lab input { font: inherit; } | ||
| + | .tc-lab button { | ||
| + | padding: 8px 14px; | ||
| + | border: 1px solid #94a3b8; | ||
| + | border-radius: | ||
| + | background: #fff; | ||
| + | color: #172033; | ||
| + | cursor: pointer; | ||
| + | } | ||
| + | .tc-lab button: | ||
| + | .tc-lab button: | ||
| + | outline: 3px solid #2563eb; | ||
| + | outline-offset: | ||
| + | } | ||
| + | .tc-lab .tc-card { | ||
| + | padding: 20px; | ||
| + | margin-top: 18px; | ||
| + | border: 1px solid #dbe3ee; | ||
| + | border-radius: | ||
| + | background: #fff; | ||
| + | } | ||
| + | .tc-lab .tc-controls { | ||
| + | display: flex; | ||
| + | gap: 10px; | ||
| + | align-items: | ||
| + | flex-wrap: wrap; | ||
| + | margin: 12px 0; | ||
| + | } | ||
| + | .tc-lab input[type=" | ||
| + | width: 110px; | ||
| + | padding: 7px 10px; | ||
| + | border: 1px solid #94a3b8; | ||
| + | border-radius: | ||
| + | background: #fff; | ||
| + | color: #172033; | ||
| + | } | ||
| + | .tc-lab input[type=" | ||
| + | .tc-lab .tc-bits { | ||
| + | display: grid; | ||
| + | grid-template-columns: | ||
| + | gap: 6px; | ||
| + | margin: 16px 0; | ||
| + | } | ||
| + | .tc-lab .tc-bit-cell { text-align: center; min-width: 0; } | ||
| + | .tc-lab .tc-bit { | ||
| + | display: block; | ||
| + | width: 100%; | ||
| + | padding: 10px 0; | ||
| + | font: bold 25px/1.2 monospace; | ||
| + | border: 2px solid #cbd5e1; | ||
| + | background: #f1f5f9; | ||
| + | } | ||
| + | .tc-lab .tc-bit[aria-pressed=" | ||
| + | background: #dbeafe; | ||
| + | border-color: | ||
| + | color: #1e40af; | ||
| + | } | ||
| + | .tc-lab .tc-sign .tc-bit[aria-pressed=" | ||
| + | background: #ffedd5; | ||
| + | border-color: | ||
| + | color: #9a3412; | ||
| + | } | ||
| + | .tc-lab .tc-weight { | ||
| + | display: block; | ||
| + | font-size: 13px; | ||
| + | padding-top: | ||
| + | color: #475569; | ||
| + | } | ||
| + | .tc-lab .tc-results { | ||
| + | display: flex; | ||
| + | flex-wrap: wrap; | ||
| + | gap: 12px; | ||
| + | margin: 12px 0; | ||
| + | } | ||
| + | .tc-lab .tc-result { | ||
| + | flex: 1 1 180px; | ||
| + | padding: 12px; | ||
| + | border-radius: | ||
| + | background: #eff6ff; | ||
| + | } | ||
| + | .tc-lab .tc-value { display: block; font-size: 28px; font-weight: | ||
| + | .tc-lab .tc-mono { | ||
| + | font-family: | ||
| + | white-space: | ||
| + | overflow-wrap: | ||
| + | } | ||
| + | .tc-lab .tc-note { color: #475569; font-size: 14px; } | ||
| + | .tc-lab .tc-feedback { | ||
| + | margin-top: 12px; | ||
| + | padding: 12px; | ||
| + | border-left: | ||
| + | background: #f1f5f9; | ||
| + | } | ||
| + | .tc-lab .tc-feedback[data-kind=" | ||
| + | border-color: | ||
| + | background: #f0fdf4; | ||
| + | } | ||
| + | .tc-lab .tc-feedback[data-kind=" | ||
| + | border-color: | ||
| + | background: #fffbeb; | ||
| + | } | ||
| + | .tc-lab .tc-primary { background: #1d4ed8; color: #fff; border-color: | ||
| + | .tc-lab .tc-primary: | ||
| + | .tc-lab .tc-target { font-size: 30px; font-weight: | ||
| + | .tc-lab [hidden] { display: none !important; } | ||
| + | @media (max-width: 520px) { | ||
| + | .tc-lab { padding: 12px; } | ||
| + | .tc-lab .tc-card { padding: 12px; } | ||
| + | .tc-lab .tc-bits { gap: 3px; } | ||
| + | .tc-lab .tc-bit { font-size: 21px; } | ||
| + | .tc-lab .tc-weight { font-size: 11px; } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | < | ||
| + | <p> | ||
| + | Eight bits can represent signed integers from < | ||
| + | Click the bits to see how the same pattern can have different meanings. | ||
| + | </p> | ||
| + | |||
| + | <section class=" | ||
| + | < | ||
| + | <div class=" | ||
| + | < | ||
| + | Signed decimal value: | ||
| + | <input data-role=" | ||
| + | </ | ||
| + | <button type=" | ||
| + | <button type=" | ||
| + | <button type=" | ||
| + | <button type=" | ||
| + | <button type=" | ||
| + | </ | ||
| + | |||
| + | <input data-role=" | ||
| + | | ||
| + | |||
| + | <div data-role=" | ||
| + | <p class=" | ||
| + | The weights below the bits apply to two's complement. | ||
| + | The leftmost bit has weight < | ||
| + | </p> | ||
| + | |||
| + | <div class=" | ||
| + | <div class=" | ||
| + | Two's complement value | ||
| + | <span data-role=" | ||
| + | </ | ||
| + | <div class=" | ||
| + | Unsigned value | ||
| + | <span data-role=" | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | <div data-role=" | ||
| + | <p data-role=" | ||
| + | |||
| + | <div class=" | ||
| + | <button type=" | ||
| + | <button type=" | ||
| + | </ | ||
| + | <div data-role=" | ||
| + | | ||
| + | </ | ||
| + | |||
| + | <section class=" | ||
| + | < | ||
| + | <p> | ||
| + | Set the eight bits to encode this number in two's complement: | ||
| + | <span data-role=" | ||
| + | </p> | ||
| + | < | ||
| + | |||
| + | <div data-role=" | ||
| + | |||
| + | <div class=" | ||
| + | <button type=" | ||
| + | <button type=" | ||
| + | <button type=" | ||
| + | <button type=" | ||
| + | </ | ||
| + | |||
| + | <p data-role=" | ||
| + | <div data-role=" | ||
| + | <div data-role=" | ||
| + | <div data-role=" | ||
| + | </ | ||
| + | |||
| + | < | ||
| + | (function () { | ||
| + | "use strict"; | ||
| + | |||
| + | const root = document.currentScript.parentElement; | ||
| + | const find = role => root.querySelector(' | ||
| + | const weights = [-128, 64, 32, 16, 8, 4, 2, 1]; | ||
| + | |||
| + | let word = 251; | ||
| + | let gameWord = 0; | ||
| + | let target = -5; | ||
| + | let solved = false; | ||
| + | let revealed = false; | ||
| + | let score = 0; | ||
| + | let completed = 0; | ||
| + | |||
| + | const binary = n => (n & 255).toString(2).padStart(8, | ||
| + | const signed = n => n >= 128 ? n - 256 : n; | ||
| + | const display = n => n < 0 ? " | ||
| + | |||
| + | function createBits(container, | ||
| + | const buttons = []; | ||
| + | weights.forEach((weight, | ||
| + | const cell = document.createElement(" | ||
| + | cell.className = " | ||
| + | |||
| + | const button = document.createElement(" | ||
| + | button.type = " | ||
| + | button.className = " | ||
| + | button.textContent = " | ||
| + | button.setAttribute(" | ||
| + | button.addEventListener(" | ||
| + | |||
| + | const label = document.createElement(" | ||
| + | label.className = " | ||
| + | label.textContent = display(weight); | ||
| + | |||
| + | cell.append(button, | ||
| + | container.append(cell); | ||
| + | buttons.push(button); | ||
| + | }); | ||
| + | return buttons; | ||
| + | } | ||
| + | |||
| + | function updateBits(buttons, | ||
| + | buttons.forEach((button, | ||
| + | const bit = (value >> (7 - index)) & 1; | ||
| + | button.textContent = bit; | ||
| + | button.setAttribute(" | ||
| + | button.setAttribute( | ||
| + | " | ||
| + | "Bit " + (7 - index) + ", weight " + weights[index] + | ||
| + | ", value " + bit + ". Click to toggle." | ||
| + | ); | ||
| + | }); | ||
| + | } | ||
| + | |||
| + | function feedback(element, | ||
| + | element.textContent = message; | ||
| + | element.dataset.kind = kind || ""; | ||
| + | } | ||
| + | |||
| + | const exploreButtons = createBits(find(" | ||
| + | word ^= 1 << bit; | ||
| + | renderExplore(); | ||
| + | feedback(find(" | ||
| + | }); | ||
| + | |||
| + | const gameButtons = createBits(find(" | ||
| + | gameWord ^= 1 << bit; | ||
| + | updateBits(gameButtons, | ||
| + | if (!solved && !revealed) { | ||
| + | feedback(find(" | ||
| + | } | ||
| + | }); | ||
| + | |||
| + | function renderExplore() { | ||
| + | const value = signed(word); | ||
| + | find(" | ||
| + | find(" | ||
| + | find(" | ||
| + | find(" | ||
| + | updateBits(exploreButtons, | ||
| + | |||
| + | const terms = weights.filter((weight, | ||
| + | find(" | ||
| + | (terms.length ? terms.map(display).join(" | ||
| + | " = " + display(value); | ||
| + | |||
| + | find(" | ||
| + | ? "The leftmost bit is 1. Read the pattern as unsigned, then subtract 256: " + | ||
| + | word + " − 256 = " + display(value) + " | ||
| + | : "The leftmost bit is 0. Unsigned and two's complement interpretations agree."; | ||
| + | } | ||
| + | |||
| + | find(" | ||
| + | const value = this.valueAsNumber; | ||
| + | const valid = Number.isInteger(value) && value >= -128 && value <= 127; | ||
| + | this.setAttribute(" | ||
| + | if (!valid) { | ||
| + | feedback(find(" | ||
| + | return; | ||
| + | } | ||
| + | word = value & 255; | ||
| + | renderExplore(); | ||
| + | feedback(find(" | ||
| + | }); | ||
| + | |||
| + | function setValue(value) { | ||
| + | word = value & 255; | ||
| + | find(" | ||
| + | renderExplore(); | ||
| + | feedback(find(" | ||
| + | } | ||
| + | |||
| + | find(" | ||
| + | setValue(Number(event.target.value)); | ||
| + | }); | ||
| + | |||
| + | root.querySelectorAll(" | ||
| + | button.addEventListener(" | ||
| + | }); | ||
| + | |||
| + | root.querySelector(' | ||
| + | const before = word; | ||
| + | const value = signed(before); | ||
| + | const inverted = before ^ 255; | ||
| + | word = (inverted + 1) & 255; | ||
| + | renderExplore(); | ||
| + | |||
| + | let message = | ||
| + | " | ||
| + | " | ||
| + | "Add 1: " | ||
| + | |||
| + | if (value === -128) { | ||
| + | message += " | ||
| + | " | ||
| + | } else if (value === 0) { | ||
| + | message += " | ||
| + | } else { | ||
| + | message += "\nThe sign has changed; the magnitude is unchanged."; | ||
| + | } | ||
| + | feedback(find(" | ||
| + | }); | ||
| + | |||
| + | root.querySelector(' | ||
| + | const before = word; | ||
| + | const value = signed(before); | ||
| + | const total = before + 1; | ||
| + | word = total & 255; | ||
| + | renderExplore(); | ||
| + | |||
| + | let message = | ||
| + | " | ||
| + | "+ 00000001 | ||
| + | "= " + total.toString(2).padStart(8, | ||
| + | "Keep 8 bits: " + binary(word) + " | ||
| + | |||
| + | if (value === 127) { | ||
| + | message += " | ||
| + | " | ||
| + | } else if (total > 255) { | ||
| + | message += "\nThe carry-out is discarded. −1 + 1 = 0: no signed overflow."; | ||
| + | } else { | ||
| + | message += "\nThe result fits: no signed overflow."; | ||
| + | } | ||
| + | feedback(find(" | ||
| + | }); | ||
| + | |||
| + | function updateScore() { | ||
| + | find(" | ||
| + | " | ||
| + | " | Completed challenges: " + completed + | ||
| + | ". Hints are allowed."; | ||
| + | } | ||
| + | |||
| + | function startChallenge(first) { | ||
| + | const previous = target; | ||
| + | if (!first) { | ||
| + | do { | ||
| + | target = -(1 + Math.floor(Math.random() * 128)); | ||
| + | } while (target === previous); | ||
| + | } | ||
| + | |||
| + | gameWord = 0; | ||
| + | solved = false; | ||
| + | revealed = false; | ||
| + | find(" | ||
| + | find(" | ||
| + | find(" | ||
| + | updateBits(gameButtons, | ||
| + | feedback(find(" | ||
| + | updateScore(); | ||
| + | } | ||
| + | |||
| + | root.querySelector(' | ||
| + | if (signed(gameWord) === target) { | ||
| + | if (!solved && !revealed) { | ||
| + | score++; | ||
| + | completed++; | ||
| + | } | ||
| + | solved = true; | ||
| + | updateScore(); | ||
| + | feedback( | ||
| + | find(" | ||
| + | " | ||
| + | ". Press Next number for another challenge.", | ||
| + | " | ||
| + | ); | ||
| + | } else { | ||
| + | feedback( | ||
| + | find(" | ||
| + | binary(gameWord) + " represents " + display(signed(gameWord)) + | ||
| + | ", not " + display(target) + ". Adjust the bits and try again.", | ||
| + | " | ||
| + | ); | ||
| + | } | ||
| + | }); | ||
| + | |||
| + | root.querySelector(' | ||
| + | const magnitude = Math.abs(target); | ||
| + | find(" | ||
| + | find(" | ||
| + | "Start with the magnitude " + magnitude + ": " + binary(magnitude) + | ||
| + | " | ||
| + | "\nThe answer must begin with 1 because the target is negative." | ||
| + | (target === -128 | ||
| + | ? " | ||
| + | " | ||
| + | : "" | ||
| + | }); | ||
| + | |||
| + | root.querySelector(' | ||
| + | if (!solved && !revealed) completed++; | ||
| + | revealed = true; | ||
| + | const magnitude = Math.abs(target); | ||
| + | const inverted = magnitude ^ 255; | ||
| + | const answer = (inverted + 1) & 255; | ||
| + | |||
| + | find(" | ||
| + | find(" | ||
| + | " | ||
| + | " | ||
| + | "Add 1: " | ||
| + | " | ||
| + | |||
| + | feedback(find(" | ||
| + | updateScore(); | ||
| + | }); | ||
| + | |||
| + | root.querySelector(' | ||
| + | startChallenge(false); | ||
| + | }); | ||
| + | |||
| + | renderExplore(); | ||
| + | startChallenge(true); | ||
| + | })(); | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
tanszek/oktatas/techcomm/encoding_integers.1791829544.txt.gz · Last modified: by knehez
