SheepDev

Numbers, units, and bits

How many bits does a large ID need?

Tools to use

Pasting an order ID into a table changes its last digit to zero. Another screen shows two supposedly consecutive IDs as the same number. Displaying a large integer and preserving every digit are different capabilities. Code that works for small values can fail only when a boundary is crossed.

Use illustrative boundary values rather than real IDs. Check whether an integer type can hold them, convert to another base, and convert back. This helps reason about representation throughout a database–API–browser–spreadsheet handoff, not just inside the database.

Does the value after 255 still fit in eight bits?

In integer ranges, choose range mode, eight bits, and unsigned. The range is 0 through 255. There are 256 possible values, but the maximum is not 256. The distinction between the number of values and the maximum persists for larger widths.

Three values across the boundary
254 = 11111110₂
255 = 11111111₂
256 = 100000000₂

Required-width mode reports eight unsigned bits for 255 and nine for 256. Increasing the value by one can require another binary digit. If sizing based on expected use, consider future growth and reserved values separately rather than checking only today's value.

Not every 64-bit range is the same

At 64 bits, compare signed and unsigned. Signed integers also represent negatives, so their positive maximum is smaller: 9,223,372,036,854,775,807 versus 18,446,744,073,709,551,615 unsigned. A description such as '64-bit column' is insufficient to establish compatibility.

Even at eight bits, signed maximum is 127. Positive 128 requires eight unsigned bits but nine signed bits. An ID that never uses negatives must still fit a receiver's signed type if that is its declared type. Being an identifier does not automatically make storage unsigned.

Round-trip a twenty-digit integer through hexadecimal

Decimal input: no grouping commas
18446744073709551615

Convert from base 10 to 16: the result is ffffffffffffffff, sixteen f characters. Feed that result back with base 16 to 10 and recover the original twenty digits. Compare every digit to confirm the integer survived the representation change. Keep it as text between tools rather than passing it through another calculator's numeric field.

One hexadecimal digit can represent four bits, so this value corresponds to sixty-four one bits. But leading zeros and the leading digit matter when inferring the minimum width from text length. The two-character string 0f still represents 15, requiring only four unsigned bits. Fixed storage width and minimum value width are different questions.

Fitting an integer type does not make Number safe

JavaScript's ordinary Number is not a 64-bit integer type. Its safe-integer upper bound is 9,007,199,254,740,991. Some larger integers are representable, but consecutive integers are no longer all guaranteed distinguishable. Successfully displaying one large value does not establish safety for every ID with the same number of digits.

A precision-check value
9007199254740993

Enter this directly into base conversion: decimal to hexadecimal yields 20000000000001. Verify the reverse conversion. If another processing step has already changed it to 9007199254740992, the original digit was lost there. Converting that altered value to BigInt later cannot infer and recover the original integer.

Should an identifier be numeric or textual?

An identifier 00123 has numeric value 123 but a distinct textual representation. Base conversion handles numbers and is not designed to preserve leading-zero counts. Decide whether the value is an arithmetic quantity or an exact-match identifier. A postal or membership code should not become numeric merely because it contains only digits.

Passing IDs as strings through an API requires agreement on the receiving type. Do not add quotes and assume the issue is solved; confirm the receiver accepts strings. Conversely, a Number conversion inside a string-based contract can be the loss boundary. Trace display, search, and CSV export as well as storage.

Test every digit at each handoff

Test values just below, at, and above a boundary rather than only one comfortable value. For unsigned eight-bit storage, use 254, 255, and 256; for Number, use consecutive values around its safe boundary. Record explicit rejection separately from rounding. Altering an out-of-range value merely to make it pass is not a fix.

Report the location and representation, such as 'fits unsigned 64-bit storage, retained as a string in the browser', rather than '64-bit is fine'. Required width informs type selection but does not guarantee a particular database column or protocol supports it. Confirm those specifications and round-trip the same values through the actual path.

The same bits can mean different signed values

The eight bits 11111111 represent 255 unsigned or -1 as signed two's complement. Converting decimal 255 to binary does not by itself reinterpret it as -1. Radix describes notation; signedness and width describe how a fixed-length field is interpreted. Before treating a logged ff as 255, check whether that field is signed.

Leading zeroes need the same care. Numerically 0010 and 10 are equal, but as product codes they may be different identifiers. A radix converter is not responsible for preserving identifier width. CSV consumers can also reinterpret text codes as numbers. Ask whether a value is a quantity to calculate with or a name to match; even small values can lose essential information through numeric conversion.

Test the boundary and its neighbors: 254, 255 and 256 for unsigned eight-bit storage, or values around 9007199254740991 for JavaScript's safe-integer boundary. Check where text becomes numeric, before and after JSON parsing or API transfer. A precise tool cannot restore digits already lost upstream. Preserve the original text and find the first stage where it changes.

Sources

Tools to use

Guides →