Inconsistent result of 10f64.powf(126.0)

Here is a very simple test:

#[test]
fn test() {
    assert_eq!(10f64.powf(126.0), 1.0e126);
}

This test passed on Windows and many Linux computers. But in my Linux virtual machine on Windows computer, it failed:

---- test stdout ----
thread 'test' panicked at 'assertion failed: `(left == right)`
  left: `1000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0`,
 right: `1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0`', src/main.rs:7:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

The result of 10f64.powf(126.0) is 1.0000000000000001e126. I have tried this test in many Linux comupters, only this one failed.

All the computers have same Intel CPU. rustc is 1.52.1.

How can I solve this problem, or is there a reasonable explanation?

Are you using the same target (e.g. x86_64-unknown-linux-gnu) on each Linux machine and on the Linux VM?

Are the Linux versions the same in that virtual machine vs. the native hosts? I suspect this comes down to the libm implementation of pow -- can you reproduce this with similar C code?

1 Like

The two results differ by 1ULP. (You can see this yourself with Float Toy .) This is, in general, allowed for all the methods on floats, with a few exceptions for the basic things (+-*/%, and trivial methods like abs). Different math libraries are only expected to be within 1ULP of the correct answer, which mean there are 2 possible results they can give while still being correct, and different implementations will end up giving different values sometimes.

A related previous conversation:

7 Likes

yes, 1.52.1

That's the compiler version number, not the target.

It's also worth noting that 1e126 is not precisely represented in f64, despite looking like a nice round number. If you factor that, 2126 is incorporated in the floating point exponent just fine, but the remaining 5126 is a 293-bit odd number, which can't be exactly represented by the 53-bit mantissa of f64.

4 Likes

The target is default, no cross compile.

I created a toally new virtual machine just now. The test still failed:

david@david-VirtualBox:~/rust/t1$ cat src/main.rs 
fn main() {
    println!("{}", 10f64.powf(126.0));
}

#[test]
fn test() {
    assert_eq!(10f64.powf(126.0), 1.0e126);
}

david@david-VirtualBox:~/rust/t1$ cargo test
    Finished test [unoptimized + debuginfo] target(s) in 0.00s
     Running unittests (target/debug/deps/t1-d1f8e0d9f6709751)

running 1 test
test test ... FAILED

failures:

---- test stdout ----
thread 'test' panicked at 'assertion failed: `(left == right)`
  left: `1000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0`,
 right: `1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0`', src/main.rs:7:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


failures:
    test

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

error: test failed, to rerun pass '--bin t1'

My toolchain is:

david@david-VirtualBox:~/rust/t1$ rustup toolchain list
stable-x86_64-unknown-linux-gnu (default)
david@david-VirtualBox:~/rust/t1$ rustc --version
rustc 1.52.1 (9bc8c42bb 2021-05-09)
david@david-VirtualBox:~/rust/t1$ cargo --version
cargo 1.52.0 (69767412a 2021-04-21)

And in my Windows which one the Linux vm running on:

MINGW64 /d/Rust/t1 (master)
$ cat src/main.rs
fn main() {
    println!("{}", 10f64.powf(126.0));
}

#[test]
fn test() {
    assert_eq!(10f64.powf(126.0), 1.0e126);
}


MINGW64 /d/Rust/t1 (master)
$ cargo test
   Compiling t1 v0.1.0 (D:\Rust\t1)
    Finished test [unoptimized + debuginfo] target(s) in 2.29s
     Running unittests (target\debug\deps\t1-88dba4b7952065ef.exe)

running 1 test
test test ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s


MINGW64 /d/Rust/t1 (master)
$ rustup toolchain list
stable-x86_64-pc-windows-msvc (default)
nightly-x86_64-pc-windows-msvc

MINGW64 /d/Rust/t1 (master)
$ cargo --version
cargo 1.52.0 (69767412a 2021-04-21)

MINGW64 /d/Rust/t1 (master)
$ rustc --version
rustc 1.52.1 (9bc8c42bb 2021-05-09)

The IEEE 754-2008 standard "recommends" that pow be rounded correctly, but I don't know if any library actually does that.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.