Floating Points and Complex Numbers
tally wants to report "average words per line". With 17 words over 4 lines the answer should be 4.25, but the first version prints 4. Fractions need floating-point numbers, and floats come with a couple of surprises worth knowing in advance.
The rule
Fractions need float64, and float64 is close, not exact.
Go has float32 and float64. A literal with a decimal point, such as x := 4.25, is float64, and that is the one to use unless memory is truly tight.
Getting a fraction. Dividing two ints is integer division, so convert before you divide:
total, lines := 17, 4
fmt.Println(total / lines) // 4
fmt.Println(float64(total) / float64(lines)) // 4.25
fmt.Println(float64(total / lines)) // 4, divided too earlyClose, not exact. Floats are stored in binary, and most decimals, like 0.1, have no exact binary form:
a, b := 0.1, 0.2
fmt.Println(a + b) // 0.30000000000000004
fmt.Println(a+b == 0.3) // falseCompare computed floats with a tolerance: math.Abs(x-y) < 1e-9. One twist: untyped constants are exact, so fmt.Println(0.1+0.2 == 0.3) with plain literals prints true. The rounding only appears once values live in float64 variables.
No crash on division by zero. A float divided by a zero float variable gives +Inf (or -Inf), and 0/0 gives NaN, which is not even equal to itself. Integer division by a zero variable, in contrast, panics.
Complex numbers are built in: complex128 (two float64s) and complex64.
c := 3 + 4i
fmt.Println(c) // (3+4i)
fmt.Println(real(c)) // 3
fmt.Println(imag(c)) // 4
fmt.Println(cmplx.Abs(c)) // 5, from math/cmplxYou will rarely need them outside signal processing or maths, but they follow the same float rules.
The shortcut
Before any division, ask "do I want a fraction?" If yes, convert first, divide second. Before any == on floats, ask "were these computed?" If yes, compare within a tolerance.
Spot the division
total / lines— both ints, so the fraction is lost.
Drills
Answer fast — trust the rule.
What is the type of r := 2.5?
total, lines := 17, 4. What does float64(total / lines) give?
a, b := 0.1, 0.2. What does fmt.Println(a+b == 0.3) print?
c := 3 + 4i. What is imag(c)?
x, zero := 1.0, 0.0. What does fmt.Println(x / zero) print?
Remember
- Fractions need float64, and float64 is close, not exact.
- Shortcut: convert first, divide second; compare computed floats within a tolerance.
- Trap:
float64(a / b)on ints is too late — the fraction is already gone.
