Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright (C) 2011 The Guava Authors
   *
   * 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 com.google.common.math;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.math.DoubleUtils.IMPLICIT_BIT;
 import static com.google.common.math.DoubleUtils.SIGNIFICAND_BITS;
 import static com.google.common.math.DoubleUtils.getSignificand;
 import static com.google.common.math.DoubleUtils.isFinite;
 import static com.google.common.math.DoubleUtils.isNormal;
 import static com.google.common.math.DoubleUtils.scaleNormalize;
 import static com.google.common.math.MathPreconditions.checkInRange;
 import static com.google.common.math.MathPreconditions.checkNonNegative;
 import static com.google.common.math.MathPreconditions.checkRoundingUnnecessary;
 import static java.lang.Math.abs;
 import static java.lang.Math.copySign;
 import static java.lang.Math.getExponent;
 import static java.lang.Math.log;
 import static java.lang.Math.rint;
 
 
A class for arithmetic on doubles that is not covered by java.lang.Math.

Author(s):
Louis Wasserman
Since:
11.0
 
 public final class DoubleMath {
   /*
    * This method returns a value y such that rounding y DOWN (towards zero) gives the same result
    * as rounding x according to the specified mode.
    */
   static double roundIntermediate(double xRoundingMode mode) {
     if (!isFinite(x)) {
       throw new ArithmeticException("input is infinite or NaN");
     }
     switch (mode) {
       case :
         return x;
 
       case :
         if (x >= 0.0 || isMathematicalInteger(x)) {
           return x;
         } else {
           return x - 1.0;
         }
 
       case :
         if (x <= 0.0 || isMathematicalInteger(x)) {
           return x;
         } else {
           return x + 1.0;
         }
 
       case :
         return x;
 
       case :
         if (isMathematicalInteger(x)) {
           return x;
         } else {
           return x + Math.copySign(1.0, x);
         }
 
       case :
         return rint(x);
 
       case : {
         double z = rint(x);
         if (abs(x - z) == 0.5) {
           return x + copySign(0.5, x);
         } else {
           return z;
         }
       }
 
       case : {
         double z = rint(x);
        if (abs(x - z) == 0.5) {
          return x;
        } else {
          return z;
        }
      }
      default:
        throw new AssertionError();
    }
  }

  
Returns the int value that is equal to x rounded with the specified rounding mode, if possible.

Throws:
java.lang.ArithmeticException if
  • x is infinite or NaN
  • x, after being rounded to a mathematical integer using the specified rounding mode, is either less than Integer.MIN_VALUE or greater than Integer.MAX_VALUE
  • x is not a mathematical integer and mode is java.math.RoundingMode.UNNECESSARY
  public static int roundToInt(double xRoundingMode mode) {
    double z = roundIntermediate(xmode);
    checkInRange(z >  - 1.0 & z <  + 1.0);
    return (intz;
  }
  private static final double MIN_INT_AS_DOUBLE = -0x1p31;
  private static final double MAX_INT_AS_DOUBLE = 0x1p31 - 1.0;

  
Returns the long value that is equal to x rounded with the specified rounding mode, if possible.

Throws:
java.lang.ArithmeticException if
  • x is infinite or NaN
  • x, after being rounded to a mathematical integer using the specified rounding mode, is either less than Long.MIN_VALUE or greater than Long.MAX_VALUE
  • x is not a mathematical integer and mode is java.math.RoundingMode.UNNECESSARY
  public static long roundToLong(double xRoundingMode mode) {
    double z = roundIntermediate(xmode);
    return (longz;
  }
  private static final double MIN_LONG_AS_DOUBLE = -0x1p63;
  /*
   * We cannot store Long.MAX_VALUE as a double without losing precision.  Instead, we store
   * Long.MAX_VALUE + 1 == -Long.MIN_VALUE, and then offset all comparisons by 1.
   */
  private static final double MAX_LONG_AS_DOUBLE_PLUS_ONE = 0x1p63;

  
Returns the BigInteger value that is equal to x rounded with the specified rounding mode, if possible.

Throws:
java.lang.ArithmeticException if
  public static BigInteger roundToBigInteger(double xRoundingMode mode) {
    x = roundIntermediate(xmode);
    if ( - x < 1.0 & x < ) {
      return BigInteger.valueOf((longx);
    }
    int exponent = getExponent(x);
    long significand = getSignificand(x);
    BigInteger result = BigInteger.valueOf(significand).shiftLeft(exponent - );
    return (x < 0) ? result.negate() : result;
  }

  
Returns true if x is exactly equal to 2^k for some finite integer k.
  public static boolean isPowerOfTwo(double x) {
    return x > 0.0 && isFinite(x) && LongMath.isPowerOfTwo(getSignificand(x));
  }

  
Returns the base 2 logarithm of a double value.

Special cases:

  • If x is NaN or less than zero, the result is NaN.
  • If x is positive infinity, the result is positive infinity.
  • If x is positive or negative zero, the result is negative infinity.

The computed result is within 1 ulp of the exact result.

If the result of this method will be immediately rounded to an int, log2(double,java.math.RoundingMode) is faster.

  public static double log2(double x) {
    return log(x) / // surprisingly within 1 ulp according to tests
  }
  private static final double LN_2 = log(2);

  
Returns the base 2 logarithm of a double value, rounded with the specified rounding mode to an int.

Regardless of the rounding mode, this is faster than (int) log2(x).

Throws:
java.lang.IllegalArgumentException if x <= 0.0, x is NaN, or x is infinite
  @SuppressWarnings("fallthrough")
  public static int log2(double xRoundingMode mode) {
    checkArgument(x > 0.0 && isFinite(x), "x must be positive and finite");
    int exponent = getExponent(x);
    if (!isNormal(x)) {
      return log2(x * mode) - ;
      // Do the calculation on a normal value.
    }
    // x is positive, finite, and normal
    boolean increment;
    switch (mode) {
      case :
        // fall through
      case :
        increment = false;
        break;
      case :
        increment = !isPowerOfTwo(x);
        break;
      case :
        increment = exponent < 0 & !isPowerOfTwo(x);
        break;
      case :
        increment = exponent >= 0 & !isPowerOfTwo(x);
        break;
      case :
      case :
      case :
        double xScaled = scaleNormalize(x);
        // sqrt(2) is irrational, and the spec is relative to the "exact numerical result,"
        // so log2(x) is never exactly exponent + 0.5.
        increment = (xScaled * xScaled) > 2.0;
        break;
      default:
        throw new AssertionError();
    }
    return increment ? exponent + 1 : exponent;
  }

  
Returns true if x represents a mathematical integer.

This is equivalent to, but not necessarily implemented as, the expression !Double.isNaN(x) && !Double.isInfinite(x) && x == Math.rint(x).

  public static boolean isMathematicalInteger(double x) {
    return isFinite(x)
        && (x == 0.0 ||
             - Long.numberOfTrailingZeros(getSignificand(x)) <= getExponent(x));
  }

  
Returns n!, that is, the product of the first n positive integers, 1 if n == 0, or e n!}, or java.lang.Double.POSITIVE_INFINITY if n! > Double.MAX_VALUE.

The result is within 1 ulp of the true value.

  public static double factorial(int n) {
    checkNonNegative("n"n);
    if (n > ) {
      return .;
    } else {
      // Multiplying the last (n & 0xf) values into their own accumulator gives a more accurate
      // result than multiplying by everySixteenthFactorial[n >> 4] directly.
      double accum = 1.0;
      for (int i = 1 + (n & ~0xf); i <= ni++) {
        accum *= i;
      }
      return accum * [n >> 4];
    }
  }
  static final int MAX_FACTORIAL = 170;
  static final double[] everySixteenthFactorial = {
      0x1.0p0,
      0x1.30777758p44,
      0x1.956ad0aae33a4p117,
      0x1.ee69a78d72cb6p202,
      0x1.fe478ee34844ap295,
      0x1.c619094edabffp394,
      0x1.3638dd7bd6347p498,
      0x1.7cac197cfe503p605,
      0x1.1e5dfc140e1e5p716,
      0x1.8ce85fadb707ep829,
      0x1.95d5f3d928edep945};

  
Returns true if a and b are within tolerance of each other.

Technically speaking, this is equivalent to Math.abs(a - b) <= tolerance || Double.valueOf(a).equals(Double.valueOf(b)).

Notable special cases include:

  • All NaNs are fuzzily equal.
  • If a == b, then a and b are always fuzzily equal.
  • Positive and negative zero are always fuzzily equal.
  • If tolerance is zero, and neither a nor b is NaN, then a and b are fuzzily equal if and only if a == b.
  • With java.lang.Double.POSITIVE_INFINITY tolerance, all non-NaN values are fuzzily equal.
  • With finite tolerance, Double.POSITIVE_INFINITY and Double.NEGATIVE_INFINITY are fuzzily equal only to themselves.
  • This is reflexive and symmetric, but not transitive, so it is not an equivalence relation and not suitable for use in java.lang.Object.equals(java.lang.Object) implementations.

    Throws:
    java.lang.IllegalArgumentException if tolerance is < 0 or NaN
    Since:
    13.0
  public static boolean fuzzyEquals(double adouble bdouble tolerance) {
    MathPreconditions.checkNonNegative("tolerance"tolerance);
    return
          Math.copySign(a - b, 1.0) <= tolerance
           // copySign(x, 1.0) is a branch-free version of abs(x), but with different NaN semantics
          || (a == b// needed to ensure that infinities equal themselves
          || (Double.isNaN(a) && Double.isNaN(b));
  }

  
Compares a and b "fuzzily," with a tolerance for nearly-equal values.

This method is equivalent to fuzzyEquals(a, b, tolerance) ? 0 : Double.compare(a, b). In particular, like java.lang.Double.compare(double,double), it treats all NaN values as equal and greater than all other values (including java.lang.Double.POSITIVE_INFINITY).

This is not a total ordering and is not suitable for use in java.lang.Comparable.compareTo(java.lang.Object) implementations. In particular, it is not transitive.

Throws:
java.lang.IllegalArgumentException if tolerance is < 0 or NaN
Since:
13.0
  public static int fuzzyCompare(double adouble bdouble tolerance) {
    if (fuzzyEquals(abtolerance)) {
      return 0;
    } else if (a < b) {
      return -1;
    } else if (a > b) {
      return 1;
    } else {
      return Booleans.compare(Double.isNaN(a), Double.isNaN(b));
    }
  }
  private static final class MeanAccumulator {
    private long count = 0;
    private double mean = 0.0;
    void add(double value) {
      checkArgument(isFinite(value));
      ++;
      // Art of Computer Programming vol. 2, Knuth, 4.2.2, (15)
       += (value - ) / ;
    }
    double mean() {
      checkArgument( > 0, "Cannot take mean of 0 values");
      return ;
    }
  }

  
Returns the arithmetic mean of the values. There must be at least one value, and they must all be finite.
  public static double mean(double... values) {
    MeanAccumulator accumulator = new MeanAccumulator();
    for (double value : values) {
      accumulator.add(value);
    }
    return accumulator.mean();
  }

  
Returns the arithmetic mean of the values. There must be at least one value. The values will be converted to doubles, which does not cause any loss of precision for ints.
  public static double mean(int... values) {
    MeanAccumulator accumulator = new MeanAccumulator();
    for (int value : values) {
      accumulator.add(value);
    }
    return accumulator.mean();
  }

  
Returns the arithmetic mean of the values. There must be at least one value. The values will be converted to doubles, which causes loss of precision for longs of magnitude over 2^53 (slightly over 9e15).
  public static double mean(long... values) {
    MeanAccumulator accumulator = new MeanAccumulator();
    for (long value : values) {
      accumulator.add(value);
    }
    return accumulator.mean();
  }

  
Returns the arithmetic mean of the values. There must be at least one value, and they must all be finite. The values will be converted to doubles, which may cause loss of precision for some numeric types.
  public static double mean(Iterable<? extends Numbervalues) {
    MeanAccumulator accumulator = new MeanAccumulator();
    for (Number value : values) {
      accumulator.add(value.doubleValue());
    }
    return accumulator.mean();
  }

  
Returns the arithmetic mean of the values. There must be at least one value, and they must all be finite. The values will be converted to doubles, which may cause loss of precision for some numeric types.
  public static double mean(Iterator<? extends Numbervalues) {
    MeanAccumulator accumulator = new MeanAccumulator();
    while (values.hasNext()) {
      accumulator.add(values.next().doubleValue());
    }
    return accumulator.mean();
  }
  private DoubleMath() {}
New to GrepCode? Check out our FAQ X