302. cbrt — powf(1.0/3.0) Says the Cube Root of -27 Is NaN
Every negative number has a real cube root — -27 is just -3. But (-27.0).powf(1.0 / 3.0) returns NaN. cbrt is the method that actually knows what a cube root is.
The naive formula falls over the moment the input goes negative:
| |
Why the NaN? powf computes x^y roughly as exp(y * ln(x)), and ln of a negative number doesn’t exist. powf can’t know that 0.3333333333333333 was meant to be ⅓ — it’s just a float that isn’t 1/3, so there’s no “odd root of a negative” special case to fall into. Mathematically fine operation, wrong tool.
The exponent being off also costs accuracy on positive inputs. 1.0 / 3.0 isn’t exactly one third, so powf computes a slightly different power:
| |
cbrt also keeps the edge cases sane where the formula produces nonsense: (-0.0).cbrt() is -0.0, and f64::NEG_INFINITY.cbrt() is NEG_INFINITY — not NaN.
Same story as this morning’s ln_1p (bite 301): when std ships a dedicated method for the operation you’re approximating with a formula, the method wins on both correctness and precision. cbrt has been stable since Rust 1.0 — and there’s a sqrt next to it you were already using.