public Money Round(RoundingPlaces places, MidpointRoundingRule rounding, out Money remainder) { Int64 unit; var placesExponent = getExponentFromPlaces(places); var fraction = roundFraction(placesExponent, rounding, out unit); var units = _units + unit; remainder = new Money(0, _decimalFraction - fraction, Asset); return(new Money(units, fraction, Asset)); }
private Int32 roundFraction(Int32 exponent, MidpointRoundingRule rounding, out Int64 unit) { var denominator = FractionScale / (Decimal)Math.Pow(10, exponent); var fraction = _decimalFraction / denominator; switch (rounding) { case MidpointRoundingRule.ToEven: fraction = Math.Round(fraction, MidpointRounding.ToEven); break; case MidpointRoundingRule.AwayFromZero: { var sign = Math.Sign(fraction); fraction = Math.Abs(fraction); // make positive fraction = Math.Floor(fraction + 0.5M); // round UP fraction *= sign; // reapply sign break; } case MidpointRoundingRule.TowardZero: { var sign = Math.Sign(fraction); fraction = Math.Abs(fraction); // make positive fraction = Math.Floor(fraction + 0.5M); // round DOWN fraction *= sign; // reapply sign break; } case MidpointRoundingRule.Up: fraction = Math.Floor(fraction + 0.5M); break; case MidpointRoundingRule.Down: fraction = Math.Ceiling(fraction - 0.5M); break; case MidpointRoundingRule.Stochastic: if (_rng == null) { _rng = new MersenneTwister(); } var coinFlip = _rng.NextDouble(); if (coinFlip >= 0.5) { goto case MidpointRoundingRule.Up; } goto case MidpointRoundingRule.Down; default: throw new ArgumentOutOfRangeException("rounding"); } fraction *= denominator; if (fraction >= FractionScale) { unit = 1; fraction = fraction - (Int32)FractionScale; } else { unit = 0; } return((Int32)fraction); }
public Money Round(RoundingPlaces places, MidpointRoundingRule rounding = MidpointRoundingRule.ToEven) { Money remainder; return(Round(places, rounding, out remainder)); }