Beispiel #1
0
        /// <summary>
        /// Rounds the given non-negative value to the "nearest" integer. Nearest is
        /// determined by the rounding method specified. Rounding methods are defined
        /// in <seealso cref="BigDecimal"/>.
        /// </summary>
        /// <param name="unscaled"> Value to round. </param>
        /// <param name="sign"> Sign of the original, scaled value. </param>
        /// <param name="roundingMethod"> Rounding method, as defined in <seealso cref="BigDecimal"/>. </param>
        /// <returns> the rounded value. </returns>
        /// <exception cref="MathArithmeticException"> if an exact operation is required but result is not exact </exception>
        /// <exception cref="MathIllegalArgumentException"> if {@code roundingMethod} is not a valid rounding method.
        /// @since 1.1 (previously in {@code MathUtils}, moved as of version 3.0) </exception>
        private static double RoundUnscaled(double unscaled, double sign, int roundingMethod)
        {
            switch (roundingMethod)
            {
            case decimal.ROUND_CEILING:
                if (sign == -1)
                {
                    unscaled = FastMath.Floor(FastMath.nextAfter(unscaled, double.NegativeInfinity));
                }
                else
                {
                    unscaled = FastMath.Ceil(FastMath.nextAfter(unscaled, double.PositiveInfinity));
                }
                break;

            case decimal.ROUND_DOWN:
                unscaled = FastMath.Floor(FastMath.nextAfter(unscaled, double.NegativeInfinity));
                break;

            case decimal.ROUND_FLOOR:
                if (sign == -1)
                {
                    unscaled = FastMath.Ceil(FastMath.nextAfter(unscaled, double.PositiveInfinity));
                }
                else
                {
                    unscaled = FastMath.Floor(FastMath.nextAfter(unscaled, double.NegativeInfinity));
                }
                break;

            case decimal.ROUND_HALF_DOWN:
            {
                unscaled = FastMath.nextAfter(unscaled, double.NegativeInfinity);
                double fraction = unscaled - FastMath.Floor(unscaled);
                if (fraction > 0.5)
                {
                    unscaled = FastMath.Ceil(unscaled);
                }
                else
                {
                    unscaled = FastMath.Floor(unscaled);
                }
                break;
            }

            case decimal.ROUND_HALF_EVEN:
            {
                double fraction = unscaled - FastMath.Floor(unscaled);
                if (fraction > 0.5)
                {
                    unscaled = FastMath.Ceil(unscaled);
                }
                else if (fraction < 0.5)
                {
                    unscaled = FastMath.Floor(unscaled);
                }
                else
                {
                    // The following equality test is intentional and needed for rounding purposes
                    if (FastMath.Floor(unscaled) / 2.0 == FastMath.Floor(FastMath.Floor(unscaled) / 2.0))
                    { // even
                        unscaled = FastMath.Floor(unscaled);
                    }
                    else
                    { // odd
                        unscaled = FastMath.Ceil(unscaled);
                    }
                }
                break;
            }

            case decimal.ROUND_HALF_UP:
            {
                unscaled = FastMath.nextAfter(unscaled, double.PositiveInfinity);
                double fraction = unscaled - FastMath.Floor(unscaled);
                if (fraction >= 0.5)
                {
                    unscaled = FastMath.Ceil(unscaled);
                }
                else
                {
                    unscaled = FastMath.Floor(unscaled);
                }
                break;
            }

            case decimal.ROUND_UNNECESSARY:
                if (unscaled != FastMath.Floor(unscaled))
                {
                    throw new MathArithmeticException();
                }
                break;

            case decimal.ROUND_UP:
                // do not round if the discarded fraction is equal to zero
                if (unscaled != FastMath.Floor(unscaled))
                {
                    unscaled = FastMath.Ceil(FastMath.nextAfter(unscaled, double.PositiveInfinity));
                }
                break;

            default:
                throw new MathIllegalArgumentException(LocalizedFormats.INVALID_ROUNDING_METHOD, roundingMethod, "ROUND_CEILING", decimal.ROUND_CEILING, "ROUND_DOWN", decimal.ROUND_DOWN, "ROUND_FLOOR", decimal.ROUND_FLOOR, "ROUND_HALF_DOWN", decimal.ROUND_HALF_DOWN, "ROUND_HALF_EVEN", decimal.ROUND_HALF_EVEN, "ROUND_HALF_UP", decimal.ROUND_HALF_UP, "ROUND_UNNECESSARY", decimal.ROUND_UNNECESSARY, "ROUND_UP", decimal.ROUND_UP);
            }
            return(unscaled);
        }