How it works
Read this part and the rest of the app explains itself.
The app holds exactly one thing: a pattern of bits, as wide as you say. Every panel on the page is a different way of looking at that same pattern — as a binary string, as a decimal number, as a float, as bytes in memory.
Change it anywhere and everything else follows. Type a hex digit, click a bit, run a calculation: the value moves in one place and every panel redraws from it. Because nothing is converted twice, no two panels can ever disagree with each other.
Two settings decide how that pattern is read: data width, which says how many bits there are, and representation, which says what they mean. Everything else on the page follows from those two.
The console
The strip of settings under the title.
Data width
Anything from 4 to 256 bits. Use a preset button, or type an exact number in the box — 12, 24 and 48 are all legal. In the two float modes the width is fixed by the format, so the box is disabled.
Changing the width keeps the value where it can:
- Widening preserves the value. In Signed mode the sign bit is
extended, so
-1in 8 bits (1111 1111) becomes-1in 16 bits (1111 1111 1111 1111), not 255. - Narrowing drops the high bits. If the value no longer fits you get an overflow indicator telling you what was kept.
Representation
Four ways to read the same bits. Note what the decimal field means in each — in the float modes it is the value, while binary, octal and hex are the stored bit pattern.
| Mode | Decimal field | Binary / octal / hex | Range | Width |
|---|---|---|---|---|
| Unsigned | the value | the same value | 0 … 2n−1 | 4–256 |
| Signed | the value, two's complement | the stored bit pattern | −2n−1 … 2n−1−1 | 4–256 |
| Float32 | the real value | the stored bit pattern | ±3.4×1038 | 32, fixed |
| Float64 | the real value | the stored bit pattern | ±1.8×10308 | 64, fixed |
Switching between modes does one of two things, and the difference matters:
- Between Unsigned, Signed and a float mode, the bit pattern is
kept — a reinterpret cast. The unsigned 32-bit value 42 becomes
5.9e-44in Float32, because that is genuinely what those bits mean as a float. This is the useful direction for reading a raw register dump. - Between Float32 and Float64, the value is kept and re-encoded.
A single-precision
0.1becomes the double nearest to it.
Display options
| Option | Off | On |
|---|---|---|
| Zero padding | 101011 | 00101011 — padded to the full width |
| Group digits | 00101011 | 0010 1011 — nibbles in binary and hex, threes in octal and decimal |
| Uppercase hex | deadbeef | DEADBEEF |
These change how values are written, never what is stored. Grouping separators are ignored when you type, so you can paste a grouped value straight back in.
Entering values
Type in any of the four fields; the other three follow on every keystroke.
| You can type | Example | Notes |
|---|---|---|
| Plain digits | 2A | Case doesn't matter |
| A base prefix | 0x2A 0b1010 0o755 | Must match the field you're in |
| A trailing marker | 2Ah 1010b | Assembler style |
| Separators | 1010 1011 1_000_000 3,000 | Spaces, underscores, commas and apostrophes are ignored |
| A leading sign | -42 +42 | Negatives belong in Signed mode |
| Exponent notation | 6.022e23 | Decimal field, float modes only |
| Named values | inf -inf nan pi e | Decimal field, float modes only |
A red outline with a message under the field means the text isn't valid for that
base — a 2 in the binary field, say. Nothing is stored until it parses.
Press Enter to normalise a field: it is rewritten with your current padding, grouping and case settings. Copy puts exactly what you see on the clipboard, separators and all.
The readout
The strip of facts under the four fields.
| Fact | Shown in | Means |
|---|---|---|
| Unsigned | integer modes | The pattern read as a plain magnitude. Highlighted when it is the active reading. |
| Signed | integer modes | The same pattern read as two's complement. Both are always shown, so you can see at a glance that 0xFF is either 255 or −1. |
| Bits set | all modes | Population count — how many 1 bits, out of the width. |
| Highest set bit | integer modes | Index of the topmost 1, or — for zero. One less than the number of bits the value actually needs. |
| Range | integer modes | The smallest and largest value this width and mode can hold. |
| Value | float modes | The shortest decimal that round-trips back to these exact bits. |
| Class | float modes | Normal, Subnormal, Zero, Infinity or NaN. |
| Bit pattern | float modes | The stored bits as hex, for pasting into a debugger. |
The overflow indicator
An Overflow badge appears in the Conversion header whenever the value you entered cannot be held.
A red bar under the fields says what was kept instead, and the field you typed in is outlined. It clears as soon as you enter a value that fits. Four things set it off:
| What you did | What the app says |
|---|---|
Typed a value wider than the register — 300 at 8 bits | 300 needs more than 8 bits — only the low 8 are kept, leaving 44. |
| Narrowed the width below the value it was holding | 1 000 does not fit in 8 bits — the register now holds 232. |
Typed a negative in Unsigned mode — -5 at 8 bits | −5 is negative, which unsigned cannot represent — stored as two's complement, which reads back as 251. |
Typed a float past the format's range — 1e39 in Float32 | 1e39 is beyond the single-precision range — stored as infinity. |
The value is still stored in every case — wrapped, truncated or saturated to infinity, exactly as hardware would. The indicator tells you that what came out is not what you put in.
The bit field
The register drawn out bit by bit.
Bits run from the most significant on the left to bit 0 on the right, in rows of 16 (8 on a narrow screen). The numbers in the margins are the bit indices at each end of the row, and the small gaps fall on byte boundaries. Click any bit to flip it — every other panel updates as you do.
In the float modes each bit is tinted by the field it belongs to, and the coloured underline shows how far each field reaches even where the bits are zero.
| Tool | Does |
|---|---|
| Clear | All bits to 0. |
| Invert | One's complement — every bit flipped. |
| Set all | All bits to 1: the unsigned maximum, or −1 in Signed. |
| Shift ‹ | Left one place. The top bit falls off the end. |
| Shift › | Right one place. Arithmetic in Signed mode, so the sign is preserved; logical otherwise, so a 0 comes in at the top. |
| Random | Fills the whole width with random bits — handy for exercising a decoder. |
IEEE-754 decomposition
Appears in the Float32 and Float64 modes.
A float is three fields packed into one word: a sign bit, a biased exponent and a
mantissa. For -22.5 in Float32 (0xC1B40000) they come out
like this:
The panel reads each one back for you. The sign bit is 1, so the number is
negative. The exponent field holds 131; subtract the bias of 127 and the real
exponent is 4. The mantissa is 0x340000, which with its implied leading
1 makes a significand of 1.40625. Put together:
(−1)1 × 24 × 1.40625 = −22.5.
The exponent field is also how you tell the classes apart, which is worth knowing when you are staring at a bit pattern:
| Exponent field | Mantissa | Class | Meaning |
|---|---|---|---|
| all zeros | zero | Zero | ±0 — the sign bit still distinguishes them |
| all zeros | non-zero | Subnormal | Gradual underflow: no implied leading 1, fixed exponent |
| all ones | zero | Infinity | ±∞ |
| all ones | non-zero | NaN | Quiet if the top mantissa bit is set, signalling if not |
| anything else | any | Normal | Implied leading 1, exponent minus bias |
Two facts underneath are worth singling out:
- Exact decimal is the value in full, every digit of it. A binary
float always terminates in decimal, so this is not a rounded display — it is why
single-precision
0.1reads as0.100000001490116119384765625. This is the number your program is actually working with. - Step to next value is the gap to the next representable float — one unit in the last place. It is how much precision you have left at this magnitude, and it grows as the value does.
Memory layout
The same value as bytes, in both byte orders.
Addresses run left to right from 0, so each row reads in the order the bytes appear in memory. Big-endian puts the most significant byte first; little-endian puts the least significant byte first, which is what x86 and ARM do by default. The highlighted byte is the one holding bit 0 — last in big-endian, first in little-endian.
So 0xC1B40000 is stored as C1 B4 00 00 on a big-endian
machine and 00 00 B4 C1 on a little-endian one. Reading a memory dump
from the wrong end is the usual reason a float comes out as nonsense.
Widths that are not a whole number of bytes are padded up with zeros at the top, and the panel says so.
Arithmetic
Both operands are read at the current width and representation.
Each operand has its own base selector, so you can add a hex value to a decimal one without converting first. Load converter value into A pulls in whatever the converter is holding; Send result to converter pushes the answer back. Press Enter in either operand to calculate.
Integer division truncates toward zero, so −7 ÷ 2 is −3, not −4, and
mod takes its sign from the left operand. Dividing by zero is refused in
integer modes; in the float modes it produces infinity, as IEEE-754 requires.
The result is shown in all four bases at once, and flags appear as chips:
| Chip | Means |
|---|---|
| overflow | The true answer doesn't fit the width. An Exact (unbounded) row appears alongside the wrapped result so you can see both. |
| carry | Unsigned addition carried out of the top bit. |
| borrow | Unsigned subtraction went below zero. |
| operand overflow | One of the operands you typed didn't fit before the sum even started. |
| nan | An undefined float operation, such as 0 ÷ 0 or ∞ − ∞. |
| div0 | Float division by zero — the result is ±infinity. |
Float arithmetic is rounded to the working precision after every step, which is
why 0.1 + 0.2 lands exactly on 0.3 in Float32 but gives
0.30000000000000004 in Float64. Switch between the two modes and run it
again to watch it happen.
Worked examples
Five things people actually come here to do.
See how −1 is stored in a 16-bit register
- Set the width to 16 and the representation to Signed.
- Type -1 in the decimal field.
Every bit lights up: FFFF. The readout shows the same pattern read as unsigned — 65 535 — which is what your code would print if the variable were declared unsigned by mistake.
Find out why 0.1 + 0.2 isn't 0.3
- Choose Float64.
- Type 0.1 in the decimal field and read the Exact decimal fact.
- In Arithmetic, set A to 0.1, B to 0.2, and calculate.
0.1 is stored as 0.1000000000000000055511151231257827…, and the sum comes out as 0.30000000000000004. Switch to Float32 and run it again: there the error falls below the precision available and you get exactly 0.3.
Check whether an 8-bit addition overflows
- Set the width to 8 and pick Unsigned or Signed.
- In Arithmetic, enter the two operands and calculate.
200 + 100 unsigned gives 44 with overflow and carry chips, and an Exact (unbounded) row showing the 300 that didn't fit. The same sum in Signed wraps differently — that is the whole point of checking both.
Decode a little-endian memory dump
- Set the width to match the field — 32 bits for four bytes.
- Reverse the dumped bytes and type them into the hex field: a dump of 00 00 B4 C1 becomes C1B40000.
- Check the Memory layout panel — its little-endian row should match your dump exactly.
Now switch to Float32 and the same bytes read as −22.5. That round trip is the fastest way to confirm you have the byte order right.
Build a bit mask by hand
- Set the width you need and choose Unsigned.
- Press Clear, then click the bits you want set.
- Copy the hex field.
The bit indices in the margins are the same numbers you would put in a shift, so a bit clicked at index 12 is the mask 1 << 12.
Good to know
Keyboard
| Key | Where | Does |
|---|---|---|
| Tab | anywhere | Moves through every control, including each bit. The focus outline is always visible. |
| Enter | a conversion field | Normalises what you typed to the current display settings. |
| Enter | an operand field | Runs the calculation. |
| Space | a bit | Flips it. |
What is remembered
Your width, representation, display options, current value and colour theme are saved in this browser and restored when you come back. Clearing site data resets everything to a 32-bit unsigned zero. Nothing is stored anywhere else.
Small print
- Everything runs in this tab. No value you type is sent anywhere, and the app works offline once loaded.
- Integer maths is exact at any width — a 256-bit multiply is computed in full before it is wrapped into the register.
- Float maths uses your machine's own IEEE-754 arithmetic rather than a simulation of it, so results match what your compiler would produce.
- In the decimal field of a float mode,
eon its own means Euler's number. Exponent notation needs a mantissa in front of it —1e5, note5.