I have the following Rust code:
use std::f64::consts as f64;
fn main() {
println!("Checking f64 PI...");
// f64::PI definition: https://github.com/rust-lang/rust/blob/e1fc9ff4a794fb069d670dded1a66f05c86f3555/library/core/src/num/f64.rs#L240
println!("Definition: pub const PI: f64 = 3.14159265358979323846264338327950288_f64;");
println!("Print it: {:.35}", f64::PI);
println!("Different after 16 significant digits ----------| ");
println!("##############################################################################");
println!("Question 1: Why do the digits differ after 16 significant digits when printed?");
println!("##############################################################################");
println!("PERFORM ASSERTIONS...");
assert_eq!(f64::PI, 3.14159265358979323846264338327950288_f64); // 36 significant digits definition
assert_eq!(f64::PI, 3.141592653589793_f64); // 16 significant digits (less then the 36 in definition)
// compares up to here -------------|
assert_eq!(f64::PI, 3.14159265358979300000000000000000000_f64); // 36 significant digits (16 used in equality comparison)
assert_ne!(f64::PI, 3.14159265358979_f64); // 15 significant digits (not equal)
println!("PERFORM EQUALITY CHECK...");
if 3.14159265358979323846264338327950288_f64 == 3.14159265358979300000000000000000000_f64 {
println!("BAD: floats considered equal even when they differ past 16 significant digits");
println!("######################################################################");
println!("Question 2: Why does equality checking use only 16 significant digits?");
println!("They are defined using 36 significant digits so why can't we perform");
println!("an equality check with this accuracy?");
println!("######################################################################");
} else {
println!("GOOD: floats considered different when they differ past 16 significant digits");
println!("NOTE: This block won't execute :(");
}
}
I understand floating point arithmetic can be tricky but wanting to know if the trickiness also affects printing and performing equality checks on f64's. Here is the output from the above code:
Checking f64 PI...
Definition: pub const PI: f64 = 3.14159265358979323846264338327950288_f64;
Print it: 3.14159265358979311599796346854418516
Different after 16 significant digits ----------|
##############################################################################
Question 1: Why do the digits differ after 16 significant digits when printed?
##############################################################################
PERFORM ASSERTIONS...
PERFORM EQUALITY CHECK...
BAD: floats considered equal even when they differ past 16 significant digits
######################################################################
Question 2: Why does equality checking use only 16 significant digits?
They are defined using 36 significant digits so why can't we perform
an equality check with this accuracy?
######################################################################