Improve precision of Duration-float operations#150933
Improve precision of Duration-float operations#150933eggyal wants to merge 1 commit intorust-lang:mainfrom
Conversation
|
Reminder, once the PR becomes ready for a review, use |
5844308 to
adc30ec
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
@rustbot ready |
cf585ba to
c7098b3
Compare
|
No, some corner cases are not quite right here. I'll add some more tests and push a fix. @rustbot author |
|
@rustbot ready |
|
@craterbot run mode=build-and-test |
|
👌 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
|
Should we run crater while our own tests are failing? Surely I should fix that first! |
|
The failure is just a changed panic string right? I don't expect anyone to be checking that |
|
We also were introducing new panics for some negative factors that previously yielded zero, which has been corrected in my latest push. @rustbot ready |
Rather than convert Duration to a float in order to multiply or divide by a floating point number, which entails a loss of precision, we instead represent both operands as u128 nanoseconds and perform integer arithmetic thereupon.
|
Once you get into floating-point arithmetic, some amount of precision loss is to be expected. I actually don't find it too surprising that multiplying by 1.0 would result in precision loss for very large durations. The main problem with the code in this PR is that it adds a huge amount of complexity for what is really an edge case. It would be more appropriate to just have a warning in the documentation which explains that this method may cause precision loss due to the use of floating-point arithmetic, even when multiplying with 1.0. @rfcbot close libs |
|
Team member @Amanieu has proposed to close this. The next step is review by the rest of the tagged team members: No concerns currently listed. Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
|
🚧 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
|
🎉 Experiment
Footnotes
|
I agree on the complexity, but I do still think the issue needs fixing. The current implementation doesn't follow the basic principle of floating point arithmetic: Compute the exact result and round to the output type. It doesn't make sense that The complexity of this PR is unfortunate, but it's mostly due to the ad hoc implementation of scaling an integer by a float. It could be significantly cleaned up with a hypothetical |
|
If we want to keep the full |
A `Duration` is essentially a 94-bit value (64-bit sec and ~30-bit ns), so there's some inherent loss when converting to floating-point for `mul_f64` and `div_f64`. We could go to greater lengths to compute these with more accuracy, like rust-lang#150933 or rust-lang#154107, but it's not clear that it's worth the effort. The least we can do is document that some rounding is to be expected, which this commit does with simple examples that only multiply or divide by `1.0`. This also changes the `f32` methods to just forward to `f64`, so we keep more of that duration precision, as the range is otherwise much more limited there.
Document precision considerations of `Duration`-float methods A `Duration` is essentially a 94-bit value (64-bit sec and ~30-bit ns), so there's some inherent loss when converting to floating-point for `mul_f64` and `div_f64`. We could go to greater lengths to compute these with more accuracy, like rust-lang#150933 or rust-lang#154107, but it's not clear that it's worth the effort. The least we can do is document that some rounding is to be expected, which this commit does with simple examples that only multiply or divide by `1.0`. This also changes the `f32` methods to just forward to `f64`, so we keep more of that duration precision, as the range is otherwise much more limited there.
Rollup merge of #155133 - cuviper:duration_fp_docs, r=the8472 Document precision considerations of `Duration`-float methods A `Duration` is essentially a 94-bit value (64-bit sec and ~30-bit ns), so there's some inherent loss when converting to floating-point for `mul_f64` and `div_f64`. We could go to greater lengths to compute these with more accuracy, like #150933 or #154107, but it's not clear that it's worth the effort. The least we can do is document that some rounding is to be expected, which this commit does with simple examples that only multiply or divide by `1.0`. This also changes the `f32` methods to just forward to `f64`, so we keep more of that duration precision, as the range is otherwise much more limited there.
|
☔ The latest upstream changes (presumably #155655) made this pull request unmergeable. Please resolve the merge conflicts. |
|
If the libs team would rather not take the complexity / slowdown here, then I think a good solution could be adding |
Document precision considerations of `Duration`-float methods A `Duration` is essentially a 94-bit value (64-bit sec and ~30-bit ns), so there's some inherent loss when converting to floating-point for `mul_f64` and `div_f64`. We could go to greater lengths to compute these with more accuracy, like rust-lang/rust#150933 or rust-lang/rust#154107, but it's not clear that it's worth the effort. The least we can do is document that some rounding is to be expected, which this commit does with simple examples that only multiply or divide by `1.0`. This also changes the `f32` methods to just forward to `f64`, so we keep more of that duration precision, as the range is otherwise much more limited there.
View all comments
Rather than convert Duration to a float in order to multiply or divide by a floating point number, which entails a loss of precision, we instead represent both operands as u128 nanoseconds and perform integer arithmetic thereupon.
This improvement in precision affects some of the documented examples.
Given that these methods have been stabilised, is it a breaking change to affect their output? If so, this PR obviously cannot be merged as-is: we might instead need to create new methods for this more precise calculation (and possibly deprecate the existing ones).
Fixes #149794
r? libs-api