From 4eb8044ae73cacd278330b07795bdd649a82fc30 Mon Sep 17 00:00:00 2001 From: Brent Worden Date: Tue, 9 Aug 2005 13:10:26 +0000 Subject: [PATCH] PR: 35904 Changed rounding methods to not rely on BigDecimal conversions which was causing numerical error. git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/math/trunk@231029 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/commons/math/util/MathUtils.java | 966 ++++++++++-------- .../commons/math/util/MathUtilsTest.java | 157 ++- xdocs/changes.xml | 4 + 3 files changed, 674 insertions(+), 453 deletions(-) diff --git a/src/java/org/apache/commons/math/util/MathUtils.java b/src/java/org/apache/commons/math/util/MathUtils.java index 3078652f7..6aba55638 100644 --- a/src/java/org/apache/commons/math/util/MathUtils.java +++ b/src/java/org/apache/commons/math/util/MathUtils.java @@ -1,17 +1,12 @@ /* - * Copyright 2003-2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Copyright 2003-2005 The Apache Software Foundation. Licensed under the Apache + * License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law + * or agreed to in writing, software distributed under the License is + * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the specific language + * governing permissions and limitations under the License. */ package org.apache.commons.math.util; @@ -20,283 +15,74 @@ import java.math.BigDecimal; /** * Some useful additions to the built-in functions in {@link Math}. - * - * @version $Revision$ $Date$ + * + * @version $Revision$ $Date: 2005-07-30 02:25:26 -0500 (Sat, 30 Jul + * 2005) $ */ public final class MathUtils { - - /** 0.0 cast as a byte. */ - private static final byte ZB = (byte) 0; - + /** -1.0 cast as a byte. */ - private static final byte NB = (byte) -1; - - /** 1.0 cast as a byte. */ - private static final byte PB = (byte) 1; - - /** 0.0 cast as a short. */ - private static final short ZS = (short) 0; - + private static final byte NB = (byte)-1; + /** -1.0 cast as a short. */ - private static final short NS = (short) -1; - + private static final short NS = (short)-1; + + /** 1.0 cast as a byte. */ + private static final byte PB = (byte)1; + /** 1.0 cast as a short. */ - private static final short PS = (short) 1; - + private static final short PS = (short)1; + + /** 0.0 cast as a byte. */ + private static final byte ZB = (byte)0; + + /** 0.0 cast as a short. */ + private static final short ZS = (short)0; + /** * Private Constructor */ private MathUtils() { - } - - /** - * Round the given value to the specified number of decimal places. The - * value is rounded using the {@link BigDecimal#ROUND_HALF_UP} method. - * @param x the value to round. - * @param scale the number of digits to the right of the decimal point. - * @return the rounded value. - * @since 1.1 - */ - public static double round(double x, int scale) { - return round(x, scale, BigDecimal.ROUND_HALF_UP); + super(); } /** - * Round the given value to the specified number of decimal places. The - * value is rounded using the given method which is any method defined in - * {@link BigDecimal}. - * @param x the value to round. - * @param scale the number of digits to the right of the decimal point. - * @param roundingMethod the rounding method as defined in - * {@link BigDecimal}. - * @return the rounded value. + * Add two integers, checking for overflow. + * + * @param x an addend + * @param y an addend + * @return the sum x+y + * @throws ArithmeticException if the result can not be represented as an + * int * @since 1.1 */ - public static double round( - double x, int scale, int roundingMethod) - { - return (new BigDecimal(new Double(x).toString()).setScale(scale, roundingMethod)) - .doubleValue(); - } - - /** - * Round the given value to the specified number of decimal places. The - * value is rounding using the {@link BigDecimal#ROUND_HALF_UP} method. - * @param x the value to round. - * @param scale the number of digits to the right of the decimal point. - * @return the rounded value. - * @since 1.1 - */ - public static float round(float x, int scale) { - return round(x, scale, BigDecimal.ROUND_HALF_UP); + public static int addAndCheck(int x, int y) { + long s = (long)x + (long)y; + if (s < Integer.MIN_VALUE || s > Integer.MAX_VALUE) { + throw new ArithmeticException("overflow: add"); + } + return (int)s; } /** - * Round the given value to the specified number of decimal places. The - * value is rounded using the given method which is any method defined in - * {@link BigDecimal}. - * @param x the value to round. - * @param scale the number of digits to the right of the decimal point. - * @param roundingMethod the rounding method as defined in - * {@link BigDecimal}. - * @return the rounded value. - * @since 1.1 - */ - public static float round(float x, int scale, int roundingMethod) { - return (new BigDecimal(new Float(x).toString()).setScale(scale, roundingMethod)).floatValue(); - } - - /** - * Returns the - * sign for double precision x. - * + * Returns an exact representation of the Binomial + * Coefficient, "n choose k", the number of + * k-element subsets that can be selected from an + * n-element set. *

- * For a double value x, this method returns +1.0 - * if x > 0, 0.0 if x = 0.0, - * and -1.0 if x < 0. Returns NaN - * if x is NaN. - * - * @param x the value, a double - * @return +1.0, 0.0, or -1.0, depending on the sign of x - */ - public static double sign(final double x) { - if (Double.isNaN(x)) { - return Double.NaN; - } - return (x == 0.0) ? 0.0 : (x > 0.0) ? 1.0 : -1.0; - } - - /** - * Returns the - * sign for float value x. - * - *

- * For a float value x, this method returns +1.0F if x > 0, 0.0F if - * x = 0.0F, and -1.0F if x < 0. Returns NaN - * if x is NaN. - * - * @param x the value, a float - * @return +1.0F, 0.0F, or -1.0F, depending on the sign of x - */ - public static float sign(final float x) { - if (Float.isNaN(x)) { - return Float.NaN; - } - return (x == 0.0F) ? 0.0F : (x > 0.0F) ? 1.0F : -1.0F; - } - - /** - * Returns the - * sign for byte value x. - * - *

- * For a byte value x, this method returns (byte)(+1) if x > 0, (byte)(0) - * if x = 0, and (byte)(-1) if x < 0. - * - * @param x the value, a byte - * @return (byte)(+1), (byte)(0), or (byte)(-1), depending on the sign of x - */ - public static byte sign(final byte x) { - return (x == ZB) ? ZB : (x > ZB) ? PB : NB; - } - - /** - * Returns the - * sign for short value x. - * - *

- * For a short value x, this method returns (short)(+1) if x > 0, (short)(0) - * if x = 0, and (short)(-1) if x < 0. - * - * @param x the value, a short - * @return (short)(+1), (short)(0), or (short)(-1), depending on the sign - * of x - */ - public static short sign(final short x) { - return (x == ZS) ? ZS : (x > ZS) ? PS : NS; - } - - /** - * Returns the - * sign for int value x. - * - *

- * For an int value x, this method returns +1 if x > 0, 0 if x = 0, - * and -1 if x < 0. - * - * @param x the value, an int - * @return +1, 0, or -1, depending on the sign of x - */ - public static int sign(final int x) { - return (x == 0) ? 0 : (x > 0) ? 1 : -1; - } - - /** - * Returns the - * sign for long value x. - * - *

- * For a long value x, this method returns +1L if x > 0, 0L if x = 0, - * and -1L if x < 0. - * - * @param x the value, a long - * @return +1L, 0L, or -1L, depending on the sign of x - */ - public static long sign(final long x) { - return (x == 0L) ? 0L : (x > 0L) ? 1L : -1L; - } - - /** - * For a double precision value x, this method returns +1.0 if x >= 0 - * and -1.0 if x < 0. Returns NaN - * if x is NaN. - * - * @param x the value, a double - * @return +1.0 or -1.0, depending on the sign of x - */ - public static double indicator(final double x) { - if (Double.isNaN(x)) { - return Double.NaN; - } - return (x >= 0.0) ? 1.0 : -1.0; - } - - /** - * For a float value x, this method returns +1.0F if x >= 0 - * and -1.0F if x < 0. Returns NaN - * if x is NaN. - * - * @param x the value, a float - * @return +1.0F or -1.0F, depending on the sign of x - */ - public static float indicator(final float x) { - if (Float.isNaN(x)) { - return Float.NaN; - } - return (x >= 0.0F) ? 1.0F : -1.0F; - } - - /** - * For a byte value x, this method returns (byte)(+1) if x >= 0 - * and (byte)(-1) if x < 0. - * - * @param x the value, a byte - * @return (byte)(+1) or (byte)(-1), depending on the sign of x - */ - public static byte indicator(final byte x) { - return (x >= ZB) ? PB : NB; - } - - /** - * For a short value x, this method returns (short)(+1) if x >= 0 - * and (short)(-1) if x < 0. - * - * @param x the value, a short - * @return (short)(+1) or (short)(-1), depending on the sign of x - */ - public static short indicator(final short x) { - return (x >= ZS) ? PS : NS; - } - - /** - * For an int value x, this method returns +1 if x >= 0 - * and -1 if x < 0. - * - * @param x the value, an int - * @return +1 or -1, depending on the sign of x - */ - public static int indicator(final int x) { - return (x >= 0) ? 1 : -1; - } - - /** - * For a long value x, this method returns +1L if x >= 0 - * and -1L if x < 0. - * - * @param x the value, a long - * @return +1L or -1L, depending on the sign of x - */ - public static long indicator(final long x) { - return (x >= 0L) ? 1L : -1L; - } - - /** - * Returns an exact representation of the - * - * Binomial Coefficient, "n choose k", - * the number of k-element subsets that can be selected from - * an n-element set. - *

- * Preconditions: