liveBook · Manning

Floating-point arithmetic

As explained in Modern C, Third Edition

A floating-point value is a finite-precision numerical value represented by a sign, an exponent, and a sequence of significand bits.

One decimal literal, three types

In C, `0.2F`, `0.2`, and `0.2L` have types `float`, `double`, and `long double`, respectively. Their displayed hexadecimal values differ: choosing a type also chooses a precision for representing the value. section 5.3

Floating-point types approximate real numbers; C also has complex floating-point types. A value has a restricted magnitude and a finite number of digits. Unlike integer arithmetic without overflow, floating-point computations generally produce approximations cut off after a certain number of binary digits. section 5.2 section 5.8

A simplified binary model builds a value from a sign `s`, an exponent `e`, and `p` bits `f₁ … fₚ`: `s × 2ᵉ × Σ(fₖ × 2⁻ᵏ)`. The exponent ranges from `e_min` to `e_max`; `p` is the precision. The cutoff position changes with the number’s magnitude—that is the “floating” part. section 5.7.8

Evaluating the bits

For `s = −1`, `e = −2`, and bits `1, 0, 1`, the model gives `−1 × 2⁻² × (2⁻¹ + 2⁻³) = −5/32`. The bits determine a value through the exponent; they are not decimal digits. section 5.7.8

TAKEAWAY — Check the type and representation before expecting an exact result.

  • `<float.h>` supplies type-dependent limits and precision information. For `double`, examples include `DBL_MAX`, `DBL_MANT_DIG`, `DBL_MIN_EXP`, and `DBL_MAX_EXP`. Precision names the number of mantissa bits, not the accuracy of a computation. section 5.7.8 section 5.8
  • Decimal notation such as `1.7E-13` uses a power of ten. Hexadecimal floating-point notation such as `0x1.7aP-13` uses a hexadecimal fraction and a power of two, making exactly representable values easier to specify. section 5.3
  • For ordinary decimal output, use `printf`’s `%g`; `%a` selects hexadecimal floating-point output. Match format specifiers and modifiers to arguments: a mismatch can cause undefined behavior. section 8.4.4
float double long double
Literal 0.2F 0.2 0.2L
Value 0x1.9999’9AP-3F 0x1.9999’9999’9999AP-3 0xC.CCCC’ CCCC’ CCCC’ CCDP-6L

Compare the hexadecimal values shown for `0.2F`, `0.2`, and `0.2L` to see how the literal’s type affects its represented value. section 5.3

Rounding can also depend on floating-point environment state, and expression contraction can be controlled. Consequently, a function using floating-point arithmetic is generally not pure enough for C23’s `[[unsequenced]]` attribute. Explicit rounding and contraction pragmas can help establish a stable environment for a carefully justified function. section 16.3

How Modern C, Third Edition covers it

How deep it goes
Derives a simplified binary value from sign, exponent, and precision bits, then identifies type limits and rounding-state constraints.
Examples
Uses `0.2F`, `0.2`, and `0.2L` value comparisons plus a sign-and-bits calculation.
What it assumes
Assumes familiarity with C types and literals while defining the sign, exponent, and precision-bit model.
What you can do after
Evaluate/understand floating-point approximations, inspect type-dependent limits, and choose suitable literals and output formats.
How it connects
Connects floating-point arithmetic to C basic types, numeric literals, formatted output, and function purity.

Also explained in

Compare how 20 books explain floating-point arithmetic →

Related concepts

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