diff options
| author | Joseph Crail <jbcrail@gmail.com> | 2014-08-26 19:46:20 -0400 |
|---|---|---|
| committer | Joseph Crail <jbcrail@gmail.com> | 2014-08-28 14:31:12 -0400 |
| commit | 687db5d887a700bccf6d752caf9b5cc8805641a0 (patch) | |
| tree | 360338902df8663624859c5b73200fc1bf6269ed /src/libnum | |
| parent | b5165321e48c1fd8422803fb40693afab7939c8c (diff) | |
| download | rust-687db5d887a700bccf6d752caf9b5cc8805641a0.tar.gz rust-687db5d887a700bccf6d752caf9b5cc8805641a0.zip | |
Fix issue #15826.
The implemented fix rounds half-way cases away from zero as described in the original comments. This rounding algorithm is sometimes called arithmetic rounding. It is described further here: http://en.wikipedia.org/wiki/Rounding#Round_half_away_from_zero I also added several new tests to prevent regressions.
Diffstat (limited to 'src/libnum')
| -rw-r--r-- | src/libnum/rational.rs | 35 |
1 files changed, 29 insertions, 6 deletions
diff --git a/src/libnum/rational.rs b/src/libnum/rational.rs index f3e4b0b21ad..6f85460ab95 100644 --- a/src/libnum/rational.rs +++ b/src/libnum/rational.rs @@ -137,15 +137,14 @@ impl<T: Clone + Integer + PartialOrd> } /// Rounds to the nearest integer. Rounds half-way cases away from zero. - /// - /// Note: This function is currently broken and always rounds away from zero. #[inline] pub fn round(&self) -> Ratio<T> { - // FIXME(#15826) if *self < Zero::zero() { - Ratio::from_integer((self.numer - self.denom + One::one()) / self.denom) + // a/b - 1/2 = (2*a - b)/(2*b) + Ratio::from_integer((self.numer + self.numer - self.denom) / (self.denom + self.denom)) } else { - Ratio::from_integer((self.numer + self.denom - One::one()) / self.denom) + // a/b + 1/2 = (2*a + b)/(2*b) + Ratio::from_integer((self.numer + self.numer + self.denom) / (self.denom + self.denom)) } } @@ -388,7 +387,11 @@ mod test { pub static _2: Rational = Ratio { numer: 2, denom: 1}; pub static _1_2: Rational = Ratio { numer: 1, denom: 2}; pub static _3_2: Rational = Ratio { numer: 3, denom: 2}; - pub static _neg1_2: Rational = Ratio { numer: -1, denom: 2}; + pub static _neg1_2: Rational = Ratio { numer: -1, denom: 2}; + pub static _1_3: Rational = Ratio { numer: 1, denom: 3}; + pub static _neg1_3: Rational = Ratio { numer: -1, denom: 3}; + pub static _2_3: Rational = Ratio { numer: 2, denom: 3}; + pub static _neg2_3: Rational = Ratio { numer: -2, denom: 3}; pub fn to_big(n: Rational) -> BigRational { Ratio::new( @@ -578,6 +581,26 @@ mod test { #[test] fn test_round() { + assert_eq!(_1_3.ceil(), _1); + assert_eq!(_1_3.floor(), _0); + assert_eq!(_1_3.round(), _0); + assert_eq!(_1_3.trunc(), _0); + + assert_eq!(_neg1_3.ceil(), _0); + assert_eq!(_neg1_3.floor(), -_1); + assert_eq!(_neg1_3.round(), _0); + assert_eq!(_neg1_3.trunc(), _0); + + assert_eq!(_2_3.ceil(), _1); + assert_eq!(_2_3.floor(), _0); + assert_eq!(_2_3.round(), _1); + assert_eq!(_2_3.trunc(), _0); + + assert_eq!(_neg2_3.ceil(), _0); + assert_eq!(_neg2_3.floor(), -_1); + assert_eq!(_neg2_3.round(), -_1); + assert_eq!(_neg2_3.trunc(), _0); + assert_eq!(_1_2.ceil(), _1); assert_eq!(_1_2.floor(), _0); assert_eq!(_1_2.round(), _1); |
