The integral part of the f64 is over the limit of the i32. I have the corresponding C++ code.
// compiler - g++
// version - 10.2.0
// standard - C++14
int32_t n_int = (long int) round(n_double);
Can you show me the rust code which does exactly this?
I tried using wraps. But instead of wrapping around, the variable takes a limit of i32, i.e. either 2147483647 or -2147483648 depending on the sign of the f64.
The other ways I considered were to
Just keep the least significant 32 bits (I know how to do this for an i64, but not an f64, also when truncated, we need to worry about the sign and the twos complement).
Subtract the limit over and over till the number gets under the limit (I don't know if I should consider MAX or MAX-MIN or something else).
I'm not sure if either method does exactly what the C code does (even in the extreme/corner cases).
Edit -
Very good solutions below. I'll just mark this for future reference.
The behavior of the C++ code is undefined if the integer part of the double cannot be represented by a long int. If you want that exact behavior, you can use f64 - Rust.
So I experimented a bit on the C++ code using a few values for the f64/double.
I think this fits the best, I'm not completely sure though.
let a: f64 = <some_f64>;
let M: i64 = i32::MAX as i64;
let m: i64 = i32::MIN as i64;
let q: i64 = M - m + 1;
let mut b: i64 = a.round() as i64 % q;
b = if b > M { b-q } else if b < m { b+q } else { b };
let c: i32 = b as i32;
dbg!(c);
To imitate C++ code which has undefined behavior seems like a fool's errand. Even if you get it right today, it could change tomorrow, with a new compiler, different optimizations...