-
-
Notifications
You must be signed in to change notification settings - Fork 14.3k
Open
Labels
A-floating-pointArea: Floating point numbers and arithmeticArea: Floating point numbers and arithmeticA-timeArea: TimeArea: TimeC-bugCategory: This is a bug.Category: This is a bug.T-libsRelevant to the library team, which will review and decide on the PR/issue.Relevant to the library team, which will review and decide on the PR/issue.
Description
The methods to multiply a Duration by a float are currently implemented by converting to that float type (as seconds), multiplying, and then converting back to a Duration. This implies unnecessary rounding that loses precision in cases that ideally wouldn't.
It is particularly surprising that multiplying by 1.0 can change a duration, as floating point multiplication by 1.0 does preserve numeric values exactly.
use std::time::Duration;
fn main() {
let d1 = Duration::from_nanos_u128(1 << 90);
let d2 = Duration::from_nanos_u128(2 << 90);
let d3 = Duration::from_nanos_u128(3 << 90);
// Each of these asserts fail
assert_eq!(d1.mul_f32(1.0), d1);
assert_eq!(d1.mul_f32(2.0), d2);
assert_eq!(d1.mul_f32(3.0), d3);
assert_eq!(d2.mul_f32(1.5), d3);
// This panics due to rounding up
Duration::MAX.mul_f32(1.0);
}I expected these methods to behave just like floating point multiplication: As if the exact result was rounded to the resulting type.
The above uses very long durations, but for more realistic examples, this can be observed with durations like:
100ms
[src/main.rs:5:5] d = 100ms
[src/main.rs:6:5] d.mul_f32(1.0) = 100.000001ms
[src/main.rs:7:5] d.mul_f32(2.0) = 200.000003ms
[src/main.rs:8:5] d.mul_f32(3.0) = 300.000012ms
[src/main.rs:9:5] d * 1 = 100ms
[src/main.rs:10:5] d * 2 = 200ms
[src/main.rs:11:5] d * 3 = 300ms
1s + 111ns
[src/main.rs:5:5] d = 1.000000111s
[src/main.rs:6:5] d.mul_f32(1.0) = 1.000000119s
[src/main.rs:7:5] d.mul_f32(2.0) = 2.000000238s
[src/main.rs:8:5] d.mul_f32(3.0) = 3.000000477s
[src/main.rs:9:5] d * 1 = 1.000000111s
[src/main.rs:10:5] d * 2 = 2.000000222s
[src/main.rs:11:5] d * 3 = 3.000000333s
Metadata
Metadata
Assignees
Labels
A-floating-pointArea: Floating point numbers and arithmeticArea: Floating point numbers and arithmeticA-timeArea: TimeArea: TimeC-bugCategory: This is a bug.Category: This is a bug.T-libsRelevant to the library team, which will review and decide on the PR/issue.Relevant to the library team, which will review and decide on the PR/issue.