Float Bit Viewer
A bit-row visualization of the IEEE 754 representation of a floating-point number. The row is split into three color-coded groups — the sign bit (warning), the exponent bits (accent), and the mantissa bits (success) — so the binary anatomy of a float is legible at a glance. Useful for teaching floating-point precision, why 0.1 + 0.2 !== 0.3, and what happens at the edges of representable range.
0
0
1
1
1
1
0
1
1
1
0
0
1
1
0
0
1
1
0
0
1
1
0
0
1
1
0
0
1
1
0
1
decodes to0.100000001
Customize
Value
0.100
Display
Installation
npx shadcn@latest add https://craftbits.dev/r/float-bit-viewer.jsonUsage
import { FloatBitViewer } from "@craft-bits/core";
<FloatBitViewer value={0.1} precision="float32" />Compare single vs. double precision:
<div className="space-y-6">
<FloatBitViewer value={0.1} precision="float32" />
<FloatBitViewer value={0.1} precision="float64" />
</div>Understanding the component
- Why a round-trip through DataView. Computing IEEE 754 bits by hand (sign / biased exponent / normalized mantissa) is error-prone — subnormals, infinities, and NaN each have their own quirks. Instead we round-trip the value through
ArrayBuffer+DataView.setFloat32/setFloat64, then read the rawUint32(orBigUint64for double precision) back out. JS gives us the exact stored bit pattern for free. - Three groups, three colors. The sign bit uses
--cb-warning, the exponent bits use--cb-accent, and the mantissa bits use--cb-success. Each "1" cell picks up a 1px ring plus an 18% tinted fill in its group color so the row reads as a binary number at a glance. - Why
getBigUint64for float64. JS numbers are themselves float64, so reading 64 bits into a plain number would lose the low bits.getBigUint64returns aBigInt, the only safe way to extract all 64 bits losslessly. - Decoded readout shows quantization. When
showDecodedis on, the footer shows what the number actually becomes after being stored at the chosen precision. For values like0.1in float32, the input was0.1but the decoded value is roughly0.10000000149, which is what the bit pattern above genuinely represents. - Smooth bit transitions. Tone changes use
SPRINGS.smoothso cells animate between 0 and 1 as the value changes. The colour transition collapses toduration: 0underprefers-reduced-motion: reduce.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
value | number | required | The number to decompose. NaN, ±Infinity, and ±0 render as their canonical bit patterns. |
precision | "float32" | "float64" | "float32" | Which IEEE 754 width to render. |
showLabels | boolean | true | Whether to render the small-caps group labels (sign, exponent, mantissa). |
showDecoded | boolean | true | Whether to render the "decodes to ..." readout. |
className | string | — | Merged onto the outer <div>. |
Accessibility
- The outer element is
role="img"with anaria-labeldescribing the precision, the decoded value, and the full binary string. - Each cell carries
role="img",data-bit(0/1), anddata-group(sign/exponent/mantissa) so consumer apps can hook custom styling or assistive tooling per-bit. - Group labels are decorative — they're marked
aria-hidden="true"since the outeraria-labelalready announces the structure. - Colour is never the only signal: every cell renders its digit, and "1" cells layer a ring plus a fill on top of the group colour so highlighted bits stay legible for colourblind users.
- The cell colour transition respects
prefers-reduced-motion: reduceand collapses to an instant swap when the user opts out.
Credits
- Extracted from:
craftingattention(app/src/lessons/primitives/viz/FloatBitViewer.tsx). The original module bundled three concerns — the bit-row decomposition, a fp16-vs-fp32 number-line comparison, and a zoomable fp16 explorer — into one component, with manual mantissa-extraction math that approximated rather than exactly reproduced the stored bit pattern. The library version is just the bit-row decomposition, but reads the exact stored bits viaDataViewso every IEEE 754 edge case renders correctly, swaps fp16 for the JS-native float32 / float64 precisions, and folds the inline colour palette into thecb-warning/cb-accent/cb-successsemantic tokens.