@@ -1006,13 +1006,45 @@ impl Duration {
10061006 /// This method will panic if result is negative, overflows `Duration` or not finite.
10071007 ///
10081008 /// # Examples
1009+ ///
10091010 /// ```
10101011 /// use std::time::Duration;
10111012 ///
10121013 /// let dur = Duration::new(2, 700_000_000);
10131014 /// assert_eq!(dur.mul_f64(3.14), Duration::new(8, 478_000_000));
10141015 /// assert_eq!(dur.mul_f64(3.14e5), Duration::new(847_800, 0));
10151016 /// ```
1017+ ///
1018+ /// Note that `f64` does not have enough bits ([`f64::MANTISSA_DIGITS`]) to represent the full
1019+ /// range of possible `Duration` with nanosecond precision, so rounding may occur even for
1020+ /// trivial operations like multiplying by 1.
1021+ ///
1022+ /// ```
1023+ /// # #![feature(float_exact_integer_constants)]
1024+ /// use std::time::Duration;
1025+ ///
1026+ /// // This is about 14.9 weeks, remaining precise to the nanosecond:
1027+ /// let weeks = Duration::from_nanos(f64::MAX_EXACT_INTEGER as u64);
1028+ /// assert_eq!(weeks, weeks.mul_f64(1.0));
1029+ ///
1030+ /// // A larger value incurs rounding in the floating-point operation:
1031+ /// let weeks = Duration::from_nanos(u64::MAX);
1032+ /// assert_ne!(weeks, weeks.mul_f64(1.0));
1033+ ///
1034+ /// // This is over 285 million years, remaining precise to the second:
1035+ /// let years = Duration::from_secs(f64::MAX_EXACT_INTEGER as u64);
1036+ /// assert_eq!(years, years.mul_f64(1.0));
1037+ ///
1038+ /// // And again larger values incur rounding:
1039+ /// let years = Duration::from_secs(u64::MAX / 2);
1040+ /// assert_ne!(years, years.mul_f64(1.0));
1041+ /// ```
1042+ ///
1043+ /// ```should_panic
1044+ /// # use std::time::Duration;
1045+ /// // In the extreme, rounding can even overflow `Duration`, which panics.
1046+ /// let _ = Duration::from_secs(u64::MAX).mul_f64(1.0);
1047+ /// ```
10161048 #[ stable( feature = "duration_float" , since = "1.38.0" ) ]
10171049 #[ must_use = "this returns the result of the operation, \
10181050 without modifying the original"]
@@ -1023,6 +1055,10 @@ impl Duration {
10231055
10241056 /// Multiplies `Duration` by `f32`.
10251057 ///
1058+ /// Since the significand of `f32` is quite limited compared to the range of `Duration`
1059+ /// -- only about 16.8ms of exact nanosecond precision -- this method currently forwards
1060+ /// to [`mul_f64`][Self::mul_f64] for greater accuracy.
1061+ ///
10261062 /// # Panics
10271063 /// This method will panic if result is negative, overflows `Duration` or not finite.
10281064 ///
@@ -1031,15 +1067,18 @@ impl Duration {
10311067 /// use std::time::Duration;
10321068 ///
10331069 /// let dur = Duration::new(2, 700_000_000);
1034- /// assert_eq!(dur.mul_f32(3.14), Duration::new(8, 478_000_641));
1070+ /// // Note that this `3.14_f32` argument already has more floating-point
1071+ /// // representation error than a direct `3.14_f64` would, so the result
1072+ /// // is slightly different from the ideal 8.478s.
1073+ /// assert_eq!(dur.mul_f32(3.14), Duration::new(8, 478_000_283));
10351074 /// assert_eq!(dur.mul_f32(3.14e5), Duration::new(847_800, 0));
10361075 /// ```
10371076 #[ stable( feature = "duration_float" , since = "1.38.0" ) ]
10381077 #[ must_use = "this returns the result of the operation, \
10391078 without modifying the original"]
10401079 #[ inline]
10411080 pub fn mul_f32 ( self , rhs : f32 ) -> Duration {
1042- Duration :: from_secs_f32 ( rhs * self . as_secs_f32 ( ) )
1081+ self . mul_f64 ( rhs. into ( ) )
10431082 }
10441083
10451084 /// Divides `Duration` by `f64`.
@@ -1048,13 +1087,45 @@ impl Duration {
10481087 /// This method will panic if result is negative, overflows `Duration` or not finite.
10491088 ///
10501089 /// # Examples
1090+ ///
10511091 /// ```
10521092 /// use std::time::Duration;
10531093 ///
10541094 /// let dur = Duration::new(2, 700_000_000);
10551095 /// assert_eq!(dur.div_f64(3.14), Duration::new(0, 859_872_611));
10561096 /// assert_eq!(dur.div_f64(3.14e5), Duration::new(0, 8_599));
10571097 /// ```
1098+ ///
1099+ /// Note that `f64` does not have enough bits ([`f64::MANTISSA_DIGITS`]) to represent the full
1100+ /// range of possible `Duration` with nanosecond precision, so rounding may occur even for
1101+ /// trivial operations like dividing by 1.
1102+ ///
1103+ /// ```
1104+ /// # #![feature(float_exact_integer_constants)]
1105+ /// use std::time::Duration;
1106+ ///
1107+ /// // This is about 14.9 weeks, remaining precise to the nanosecond:
1108+ /// let weeks = Duration::from_nanos(f64::MAX_EXACT_INTEGER as u64);
1109+ /// assert_eq!(weeks, weeks.div_f64(1.0));
1110+ ///
1111+ /// // A larger value incurs rounding in the floating-point operation:
1112+ /// let weeks = Duration::from_nanos(u64::MAX);
1113+ /// assert_ne!(weeks, weeks.div_f64(1.0));
1114+ ///
1115+ /// // This is over 285 million years, remaining precise to the second:
1116+ /// let years = Duration::from_secs(f64::MAX_EXACT_INTEGER as u64);
1117+ /// assert_eq!(years, years.div_f64(1.0));
1118+ ///
1119+ /// // And again larger values incur rounding:
1120+ /// let years = Duration::from_secs(u64::MAX / 2);
1121+ /// assert_ne!(years, years.div_f64(1.0));
1122+ /// ```
1123+ ///
1124+ /// ```should_panic
1125+ /// # use std::time::Duration;
1126+ /// // In the extreme, rounding can even overflow `Duration`, which panics.
1127+ /// let _ = Duration::from_secs(u64::MAX).div_f64(1.0);
1128+ /// ```
10581129 #[ stable( feature = "duration_float" , since = "1.38.0" ) ]
10591130 #[ must_use = "this returns the result of the operation, \
10601131 without modifying the original"]
@@ -1065,6 +1136,10 @@ impl Duration {
10651136
10661137 /// Divides `Duration` by `f32`.
10671138 ///
1139+ /// Since the significand of `f32` is quite limited compared to the range of `Duration`
1140+ /// -- only about 16.8ms of exact nanosecond precision -- this method currently forwards
1141+ /// to [`div_f64`][Self::div_f64] for greater accuracy.
1142+ ///
10681143 /// # Panics
10691144 /// This method will panic if result is negative, overflows `Duration` or not finite.
10701145 ///
@@ -1073,17 +1148,18 @@ impl Duration {
10731148 /// use std::time::Duration;
10741149 ///
10751150 /// let dur = Duration::new(2, 700_000_000);
1076- /// // note that due to rounding errors result is slightly
1077- /// // different from 0.859_872_611
1078- /// assert_eq!(dur.div_f32(3.14), Duration::new(0, 859_872_580));
1151+ /// // Note that this `3.14_f32` argument already has more floating-point
1152+ /// // representation error than a direct `3.14_f64` would, so the result
1153+ /// // is slightly different from the ideally rounded 0.859_872_611.
1154+ /// assert_eq!(dur.div_f32(3.14), Duration::new(0, 859_872_583));
10791155 /// assert_eq!(dur.div_f32(3.14e5), Duration::new(0, 8_599));
10801156 /// ```
10811157 #[ stable( feature = "duration_float" , since = "1.38.0" ) ]
10821158 #[ must_use = "this returns the result of the operation, \
10831159 without modifying the original"]
10841160 #[ inline]
10851161 pub fn div_f32 ( self , rhs : f32 ) -> Duration {
1086- Duration :: from_secs_f32 ( self . as_secs_f32 ( ) / rhs)
1162+ self . div_f64 ( rhs. into ( ) )
10871163 }
10881164
10891165 /// Divides `Duration` by `Duration` and returns `f64`.
0 commit comments