public void Currency_can_round(CurrencyRoundingMethod method, decimal value, decimal result) { value.Round(method).ShouldEqual(result); }
/// <summary> /// Rounds a currency value /// </summary> /// <param name="value">Value to round</param> /// <param name="method">Currency rounding method</param> /// <returns>Rounded value</returns> /// <see cref="https://en.wikipedia.org/wiki/Cash_rounding"/> public static decimal Round(this decimal value, CurrencyRoundingMethod method) { var result = Math.Round(value, 2); var frac = (result - Math.Truncate(result)) * 10; if (frac == decimal.Zero) { return(result); } switch (method) { case CurrencyRoundingMethod.Down005: case CurrencyRoundingMethod.Up005: frac = (frac - Math.Truncate(frac)) * 10; if (method == CurrencyRoundingMethod.Down005) { frac = frac < 5 ? -1 * frac : 5 - frac; } else { frac = (frac < 5 ? 5 : 10) - frac; } result += frac / 100; break; case CurrencyRoundingMethod.Down01: case CurrencyRoundingMethod.Up01: frac = (frac - Math.Truncate(frac)) * 10; if (method == CurrencyRoundingMethod.Down01 && frac == 5) { frac = -5; } else { frac = frac < 5 ? -1 * frac : 10 - frac; } result += frac / 100; break; case CurrencyRoundingMethod.Interval05: frac *= 10; if (frac < 25) { frac *= -1; } else { frac = (frac < 50 || frac < 75 ? 50 : 100) - frac; } result += frac / 100; break; case CurrencyRoundingMethod.Interval1: case CurrencyRoundingMethod.Up1: frac *= 10; if (method == CurrencyRoundingMethod.Up1 && frac > 0) { result = Math.Truncate(result) + 1; } else { result = frac < 50 ? Math.Truncate(result) : Math.Truncate(result) + 1; } break; } return(result); }