Repository navigation
Open
Labels
A-floating-pointArea: Floating point numbers and arithmeticArea: Floating point numbers and arithmeticA-timeArea: `std::time`Area: `std::time`C-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
Reacted by teor
Metadata
Metadata
Assignees
Labels
A-floating-pointArea: Floating point numbers and arithmeticArea: Floating point numbers and arithmeticA-timeArea: `std::time`Area: `std::time`C-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.
Activity
Fix precision loss in Duration::mul_f32/f64 and div_f32/f64
tgross35 commentedon May 18, 2026
The library team decided against changing these reasonably fast implementations to one that is slower but more accurate, so #155133 updated documentation to illustrate the precision issue.
I think it could be a good idea to ACP
mul_f128/div_f128and make sure those versions are correctly rounded, then (once stable) mention it in thef32/f64methods for users who want correct rounding.