Closed
Description
We have recently observed some very strange behaviour related to float handling, that seems to be linked to float parsing (01mf02/jaq#243).
Consider the following program:
fn main() {
let t: f64 = "2.0".parse().unwrap();
let z: f64 = "0.0".parse().unwrap();
std::dbg!(t.to_bits(), z.to_bits());
std::dbg!((t / z).total_cmp(&(z / z)));
let t: f64 = 2.0;
let z: f64 = 0.0;
std::dbg!(t.to_bits(), z.to_bits());
std::dbg!((t / z).total_cmp(&(z / z)));
}
This yields:
[src/main.rs:4:5] t.to_bits() = 4611686018427387904
[src/main.rs:4:5] z.to_bits() = 0
[src/main.rs:5:5] (t / z).total_cmp(&(z / z)) = Greater
[src/main.rs:9:5] t.to_bits() = 4611686018427387904
[src/main.rs:9:5] z.to_bits() = 0
[src/main.rs:10:5] (t / z).total_cmp(&(z / z)) = Less
Given that for both t
and z
, their bits are the same, I expected total_cmp
to yield the same outputs; however, one yields Greater
, the other yields Less
!
I then refactored the program to an (IMO) equivalent one:
fn test(t: f64, z: f64) {
std::dbg!(t.to_bits(), z.to_bits());
std::dbg!((t / z).total_cmp(&(z / z)));
}
fn main() {
test("2.0".parse().unwrap(), "0.0".parse().unwrap());
test(2.0, 0.0);
}
Now, the output of total_cmp
is the same!
[src/main.rs:2:5] t.to_bits() = 4611686018427387904
[src/main.rs:2:5] z.to_bits() = 0
[src/main.rs:3:5] (t / z).total_cmp(&(z / z)) = Greater
[src/main.rs:2:5] t.to_bits() = 4611686018427387904
[src/main.rs:2:5] z.to_bits() = 0
[src/main.rs:3:5] (t / z).total_cmp(&(z / z)) = Greater
This occurs both with cargo run
and cargo run --release
.
Could this be a compiler bug?
Meta
rustc --version --verbose
:
rustc 1.83.0 (90b35a623 2024-11-26)
binary: rustc
commit-hash: 90b35a6239c3d8bdabc530a6a0816f7ff89a0aaf
commit-date: 2024-11-26
host: x86_64-unknown-linux-gnu
release: 1.83.0
LLVM version: 19.1.1