-
Notifications
You must be signed in to change notification settings - Fork 13.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
<{f16,f32,f64,f128} as Rem>::rem
documented definition is misleading w.r.t. intermediate rounding
#133758
Comments
Notably, and perhaps uncoincidentally, C's
...and the same mismatch: unsafe extern "C" {
safe fn fmod(x: f64, y: f64) -> f64;
}
fn main() {
let (x, y) = (11f64, 1.1f64);
assert_eq!(x - (x / y).trunc() * y, fmod(x, y));
//~^ PANIC
// assertion `left == right` failed
// left: 0.0
// right: 1.0999999999999992
} |
Indeed, Rust's floating point |
Yes, and the C docs state it even more clearly. They say, "it is exactly the value...". |
Yes, it is mathematically exact:
(sorry, the numbers get rather large with IMO, this is a bug in the documentation. Float |
|
edit: I misinterpreted the C standard. See the next message. So,
(in addition to the exact result of
|
No, this is incorrect. The exact value is the only value that is allowed by the C standard (for an implementation that supports IEEE-754 with subnormals), as specified by F.10.7.1:
The C expression
That's a mathematical formula, not a C expression (as is clear by the lack of a |
Agreeing and extending, IEEE 754-2008 says in 5.3.1:
Then C23 F.10.7.1 says:
So, for 11 and 1.1, remainder(11., 1.1) = exact!(11. - 1.1 * 10.) = -10f64.mul_add(1.1, -11.) = -0.0000000000000008881784197001252;
fmod(11., 1.1) = remainder(11., 1.1) + 1.1 = 1.0999999999999992; |
Hello @traviscross , I am interested to work on this issue to fix |
This is a duplicate of #107904. |
Actually, I don't think this is a duplicate of that. This is a separate documentation bug. We just need to say explicitly in the docs that the stated calculation, |
OK but then title of the issue should be clarified. |
<{f16,f32,f64,f128} as Rem>::rem
are not remainder of truncated division, as documented<{f16,f32,f64,f128} as Rem>::rem
documented definition is misleading w.r.t. intermediate rounding
Our documentation for
impl Rem for {f16, f32, f64, f128}
says:But that's not true. E.g.:
This mismatch creates a hazard when trying to correctly encode algorithms that rely on this semantic.
This tripped me up, e.g., when authoring:
{f16,f32,f64,f128}::div_euclid
#133755cc #133485 #107904
cc @cuviper @Noratrieb @tczajka @Neutron3529 @BartMassey
The text was updated successfully, but these errors were encountered: