liveBook · Manning

Precision

As explained in Modern C

Precision is the C-standard property that constrains the number of distinguishable or representable digits and thereby the valid range of a type.

A 16-bit unsigned value

Suppose an unsigned type has precision p = 16. The value 240 has bits 4, 5, 6, and 7 set. Shifting it left by 2 gives 960, with bits 6 through 9 set. Shifting it left by 9 would move one bit to position 16, which does not fit; the resulting unsigned value is 57344. Precision determines which bit positions exist. section 5.7.1 section 5.7.3

Precision is a property of a C type, not a promise about the accuracy of a calculation. It helps determine the type’s valid range. The C standard constrains the precision of basic types rather than prescribing one precision for every implementation. Distinct types can even have the same precision. section 5.2

Its consequences depend on the kind of number:

  • For an unsigned integer, precision p is the number of binary digits in its representation. Its values run from 0 through 2^p − 1. Limits such as UINT_MAX, ULONG_MAX, and ULLONG_MAX expose the corresponding maximum values. section 5.7.1
  • For a left shift, bits moved beyond the available positions are omitted, and the right operand must be less than the precision. Bitwise complement also depends on precision: it acts on the type’s full set of bit positions. section 5.7.3 section 5.7.2
  • For floating-point data, precision p counts bits in the mantissa. Together with the exponent bounds, it describes which values the type can represent. Intermediate computations can cut off digits, so familiar algebraic rearrangements need care. section 5.7.7

TAKEAWAY: Ask what precision means for the type at hand. For a typical double, DBL_MANT_DIG reports a mantissa precision of 53 bits; it does not say that every floating-point calculation is accurate to 53 bits. The “precision” field in a printf format is a separate formatting control, not a change to the argument’s type. section 5.7.7 section 8.3.4

Table 5.4. Bounds for scalar types used in this book (view table figure)

Name

[min, max]

Where

Typical

size_t [0, SIZE_MAX] <stdint.h> [0, 2w –1], w = 32, 64
double [±DBL_MIN, ±DBL_MAX] <float.h> [±2–w–2,±2w], w = 1024
signed [INT_MIN, INT_MAX] <limits.h> [–2w, 2w –1], w = 31
unsigned [0, UINT_MAX] <limits.h> [0, 2w –1], w = 32
bool [false, true] <stdbool.h> [0, 1]
ptrdiff_t [PTRDIFF_MIN, PTRDIFF_MAX] <stdint.h> [–2w, 2w –1], w = 31, 63
char [CHAR_MIN, CHAR_MAX] <limits.h> [0, 2w –1], w = 7, 8
unsigned char [0, UCHAR_MAX ] <limits.h> [0, 255]

Compare the listed scalar bounds and the header macros that expose them; typical bounds are examples, not universal type precisions. section 5.7.1

How Modern C covers it

How deep it goes
Defines integer precision as a bit count and floating-point precision as a mantissa-bit count, then works through their practical consequences.
Examples
Works through a 16-bit unsigned value and its shifts, and gives mantissa and exponent values for a floating-point example.
What it assumes
Introduces binary digits and mantissa bits while using basic C type and operator notation.
What you can do after
Evaluate/understand type ranges and floating-point limitations, and check whether an unsigned shift count is valid.
How it connects
Connects precision to unsigned integers, bit sets, shift operators, floating-point representation, and type limits.

Also explained in

Compare how 9 books explain precision →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Modern C. The section links point to the parts of the book it draws on.