Chapter 3 — Teaching Notes
One-line purpose. Give students exact command of how Fortran represents numbers (types + kinds) and
computes with them (mixed-mode + the integer-division trap), and establish the real(dp) house style and the
project's kinds module — the numerical bedrock every later chapter stands on.
Key ideas to emphasize
- The integer-division trap is the chapter's center of gravity.
1/2 == 0is not a curiosity; it is the single most common wrong-answer bug students will ship, and the compiler cannot warn about it. Drill the mental model: the type of a subexpression is decided by its operands, before the result is assigned. Arealon the left never rescues integer division on the right. - Precision is a decision, not a default. Plain
realis single precision (~7 digits). Make students physically uncomfortable writing barerealfor a physical quantity.dp = selected_real_kind(15, 307),real(dp),_dpliterals — this is house style from now to Chapter 38. - Request the requirement, not the representation.
selected_real_kind(15, 307)states "I need 15 digits";real(8)hardcodes a compiler-specific number. The kind-number output (8on gfortran) is a teaching moment against hardcoding, not a fact to memorize. modvsmodulo. They agree for positive arguments and split on the sign for negatives. Students only hit this at boundaries (periodic domains), which is exactly where simulations break — so plant it now.
Misconceptions to preempt
- "The variable is
real, so the division is real." (No — operand types decide; assignment is too late.) - "A decimal point in the output means real arithmetic happened." (No —
f8.3prints any real, including one widened from an integer quotient at the last moment. See CS-01.) - "
real(8)is the way to get double precision." (Compiler-specific; useselected_real_kind.) - "Double precision is slower, so single is a downgrade." (Single is often faster — memory-bound codes move half the bytes; the trade-off is accuracy, not speed. Don't let "double = better" go unchallenged.)
- "Trig takes degrees." (Radians.
sin(30.0_dp)is a classic silent bug.) - "
9.81and9.81_dpare the same." (The first is a single-precision literal, rounded before it is widened.)
A live demonstration (5–8 minutes)
Type the temperature-conversion bug live: c = 5 / 9 * (f - 32.0_dp). Compile with -Wall — no warnings —
and run: every temperature comes out 0.0. Ask the class why before revealing it. Then fix only the
fraction (5.0_dp / 9.0_dp) and rerun to 37.0. In under ten minutes students see (a) that clean-compiling
code can be dead wrong, (b) that -Wall cannot catch it, and (c) the exact fix. Follow with the
kinds_demo program to show precision(1.0) = 6 vs precision(1.0_dp) = 15 on the projector — the whole
case for dp in two numbers.
Class-time budget (~50 min)
- 8 min: the six types; declaration;
implicit nonestill watching (§3.1). - 12 min: kinds,
selected_real_kind,dp, single-vs-double precision (§3.2) — the livekinds_demo. - 15 min: mixed-mode + the integer-division trap (§3.3–3.4) — the live conversion bug;
modvsmodulo. - 8 min: math intrinsics (radians!) and
parameter(§3.5–3.6). - 7 min: formatted output sketch (§3.7) and launch the
kinds.f90project increment.
Prerequisites to review
Chapter 2: implicit none, the compile command (gfortran -std=f2018 -Wall), and the compile–link–run
cycle. Confirm every student can compile and run a one-line program before class — the exercises are almost
all "type, compile, and run," and an unresolved install blocks the whole session.
Connections
Back: Ch. 1 (heat-solver origin; "performance is not accidental"), Ch. 2 (implicit none, flags).
Forward: Ch. 4 (the time loop that consumes these constants), Ch. 5 (types become array types), Ch. 6
(intent), Ch. 7 (edit descriptors in full), Ch. 8 (modules — kinds grows up), Ch. 20 (why floating point
is approximate — the depth deferred here), Ch. 24 (the stability condition behind dt_max). Naming these
payoffs keeps the dp discipline from feeling like arbitrary ceremony.