Java/Data Type/Number

Материал из Java эксперт
Версия от 06:19, 1 июня 2010; Admin (обсуждение | вклад) (1 версия)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Check if number are in a given range

   
/*
 * Copyright 2008-2009 the original author or 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.
 */
import java.math.BigDecimal;
import java.math.BigInteger;
/**
 * Check if number are in a given range 
 * 
 * @author Cedric Chabanois (cchabanois at gmail.ru)
 *
 */
public class NumberInRange {
  public static final BigInteger BYTE_MIN = BigInteger
      .valueOf((long) Byte.MIN_VALUE);
  public static final BigInteger BYTE_MAX = BigInteger
      .valueOf((long) Byte.MAX_VALUE);
  public static final BigInteger SHORT_MIN = BigInteger
      .valueOf((long) Short.MIN_VALUE);
  public static final BigInteger SHORT_MAX = BigInteger
      .valueOf((long) Short.MAX_VALUE);
  public static final BigInteger INTEGER_MIN = BigInteger
      .valueOf((long) Integer.MIN_VALUE);
  public static final BigInteger INTEGER_MAX = BigInteger
      .valueOf((long) Integer.MAX_VALUE);
  public static final BigInteger LONG_MIN = BigInteger
      .valueOf(Long.MIN_VALUE);
  public static final BigInteger LONG_MAX = BigInteger
      .valueOf(Long.MAX_VALUE);
  public static final BigDecimal FLOAT_MAX = new BigDecimal(Float.MAX_VALUE);
  public static final BigDecimal FLOAT_MIN = new BigDecimal(-Float.MAX_VALUE);
  public static final BigDecimal DOUBLE_MAX = new BigDecimal(Double.MAX_VALUE);
  public static final BigDecimal DOUBLE_MIN = new BigDecimal(
      -Double.MAX_VALUE);
  public static boolean isInByteRange(Number number) {
    return isInRange(number, BYTE_MIN, BYTE_MAX);
  }
  public static boolean isInShortRange(Number number) {
    return isInRange(number, SHORT_MIN, SHORT_MAX);
  }
  public static boolean isInIntegerRange(Number number) {
    return isInRange(number, INTEGER_MIN, INTEGER_MAX);
  }
  public static boolean isInLongRange(Number number) {
    return isInRange(number, LONG_MIN, LONG_MAX);
  }
  public static boolean isInRange(Number number, BigInteger min,
      BigInteger max) {
    try {
      BigInteger bigInteger = null;
      if (number instanceof Byte || number instanceof Short
          || number instanceof Integer || number instanceof Long) {
        bigInteger = BigInteger.valueOf(number.longValue());
      } else if (number instanceof Float || number instanceof Double) {
        bigInteger = new BigDecimal(number.doubleValue())
            .toBigInteger();
      } else if (number instanceof BigInteger) {
        bigInteger = (BigInteger) number;
      } else if (number instanceof BigDecimal) {
        bigInteger = ((BigDecimal) number).toBigInteger();
      } else {
        // not a standard number
        bigInteger = new BigDecimal(number.doubleValue())
            .toBigInteger();
      }
      return max.rupareTo(bigInteger) >= 0
          && min.rupareTo(bigInteger) <= 0;
    } catch (NumberFormatException e) {
      return false;
    }
  }
  public static boolean isInRange(Number number, BigDecimal min,
      BigDecimal max) {
    try {
      BigDecimal bigDecimal = null;
      if (number instanceof Byte || number instanceof Short
          || number instanceof Integer || number instanceof Long) {
        bigDecimal = new BigDecimal(number.longValue());
      } else if (number instanceof Float || number instanceof Double) {
        bigDecimal = new BigDecimal(number.doubleValue());
      } else if (number instanceof BigInteger) {
        bigDecimal = new BigDecimal((BigInteger) number);
      } else if (number instanceof BigDecimal) {
        bigDecimal = (BigDecimal) number;
      } else {
        bigDecimal = new BigDecimal(number.doubleValue());
      }
      return max.rupareTo(bigDecimal) >= 0
          && min.rupareTo(bigDecimal) <= 0;
    } catch (NumberFormatException e) {
      return false;
    }
  }
  public static boolean isInFloatRange(Number number) {
    return isInRange(number, FLOAT_MIN, FLOAT_MAX);
  }
  public static boolean isInDoubleRange(Number number) {
    return isInRange(number, DOUBLE_MIN, DOUBLE_MAX);
  }
}





Check Number properties and convert from Number

   
/**
 * Copyright 2004, 2005, 2006 Odysseus Software GmbH
 *
 * 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.
 */ 
import java.math.BigDecimal;
import java.math.BigInteger;
/**
 * Number utilities.
 * 
 * Allows to convert between different <code>java.lang.Number</code>
 * implementations with a minimum of lost information regarding the
 * value of the represented number. Additionally, a few number tests
 * are implemented and exact comparisons of arbitrary numbers may be
 * performed.
 *
 * NOTE: Though some of the methods may give more or less useful results
 * for custom number implementations, they are intended to work only
 * with the predefined types (i.e., <code>Byte, Short, Integer, Long,
 * Float, Double, BigInteger, BigDecimal</code>).
 *
 * @author Oliver Stuhr
 */
public class NumberUtils {
  /**
   * Answers <code>true</code> iff the given number is an instance of
   * <code>java.math.BigDecimal</code> or <code>java.math.BigInteger</code>.
   *
   * @param number
   * @return boolean
   */
  public static boolean isBig(Number number) {
    return number instanceof BigDecimal || number instanceof BigInteger;
  }
  /**
   * Answers <code>true</code> iff the given number is an instance of
   * <code>Byte</code>, <code>Short</code>, <code>Integer</code> or <code>Long</code>.
   *
   * @param number
   * @return boolean
   */
  public static boolean isLongCompatible(Number number) {
    return number instanceof Byte || number instanceof Short || number instanceof Integer || number instanceof Long;
  }
  /**
   * Answers <code>true</code> iff the given number is an instance of
   * <code>Float</code> or <code>Double</code>.
   *
   * @param number
   * @return boolean
   */
  public static boolean isDoubleCompatible(Number number) {
    return number instanceof Float || number instanceof Double;
  }
  /**
   * Answers <code>true</code> iff the given number is infinite (i.e., is
   * a <code>Float</code> or <code>Double</code> containing one of the
   * predefined constant values representing positive or negative infinity).
   *
   * @param number
   * @return boolean
   */
  public static boolean isInfinite(Number number) {
    if (number instanceof Double && ((Double)number).isInfinite())
      return true;
    if (number instanceof Float && ((Float)number).isInfinite())
      return true;
    return false;
  }
  /**
   * Answers <code>true</code> iff the given number is "not a number"
   * (i.e., is a <code>Float</code> or <code>Double</code> containing
   * one of the predefined constant values representing <code>NaN</code>).
   *
   * @param number
   * @return boolean
   */
  public static boolean isNaN(Number number) {
    if (number instanceof Double && ((Double)number).isNaN())
      return true;
    if (number instanceof Float && ((Float)number).isNaN())
      return true;
    return false;
  }
  /**
   * Answers the signum function of the given number
   * (i.e., <code>-1</code> if it is negative, <code>0</code>
   * if it is zero and <code>1</code> if it is positive).
   *
   * @param number
   * @return int
   * @throws ArithmeticException The given number is <code>null</code> or "not a number".
   */
  public static int signum(Number number) throws ArithmeticException {
    if (number == null || isNaN(number))
      throw new ArithmeticException("Argument must not be null or NaN.");
    if (isLongCompatible(number)) {
      long value = number.longValue();
      return value < 0 ? -1 : value == 0 ? 0 : 1;
    } else if (number instanceof BigInteger)
      return ((BigInteger)number).signum();
    else   if (number instanceof BigDecimal)
      return ((BigDecimal)number).signum();
    else {  // => isDoubleCompatible(number) or unknown Number type
      double value = number.doubleValue();
      return value < 0 ? -1 : value == 0 ? 0 : 1;
    }
  }
  /**
   * Converts the given number to a <code>Byte</code> (by using <code>byteValue()</code>).
   *
   * @param number
   * @return java.lang.Byte
   * @throws IllegalArgumentException The given number is "not a number" or infinite.
   */
  public static Byte toByte(Number number) throws IllegalArgumentException {
    if (number == null || number instanceof Byte)
      return (Byte)number;
    if (isNaN(number) || isInfinite(number))
      throw new IllegalArgumentException("Argument must not be NaN or infinite.");
    return new Byte(number.byteValue());
  }
  /**
   * Converts the given number to a <code>Short</code> (by using <code>shortValue()</code>).
   *
   * @param number
   * @return java.lang.Short
   * @throws IllegalArgumentException The given number is "not a number" or infinite.
   */
  public static Short toShort(Number number) throws IllegalArgumentException {
    if (number == null || number instanceof Short)
      return (Short)number;
    if (isNaN(number) || isInfinite(number))
      throw new IllegalArgumentException("Argument must not be NaN or infinite.");
    return new Short(number.shortValue());
  }
  /**
   * Converts the given number to a <code>Integer</code> (by using <code>intValue()</code>).
   *
   * @param number
   * @return java.lang.Integer
   * @throws IllegalArgumentException The given number is "not a number" or infinite.
   */
  public static Integer toInteger(Number number) throws IllegalArgumentException {
    if (number == null || number instanceof Integer)
      return (Integer)number;
    if (isNaN(number) || isInfinite(number))
      throw new IllegalArgumentException("Argument must not be NaN or infinite.");
    return new Integer(number.intValue());
  }
  /**
   * Converts the given number to a <code>Long</code> (by using <code>longValue()</code>).
   *
   * @param number
   * @return java.lang.Long
   * @throws IllegalArgumentException The given number is "not a number" or infinite.
   */
  public static Long toLong(Number number) throws IllegalArgumentException {
    if (number == null || number instanceof Long)
      return (Long)number;
    if (isNaN(number) || isInfinite(number))
      throw new IllegalArgumentException("Argument must not be NaN or infinite.");
    return new Long(number.longValue());
  }
  /**
   * Converts the given number to a <code>Float</code> (by using <code>floatValue()</code>).
   *
   * @param number
   * @return java.lang.Float
   */
  public static Float toFloat(Number number) {
    return number == null || number instanceof Float ? (Float)number : new Float(number.floatValue());
  }
  /**
   * Converts the given number to a <code>Double</code> (by using <code>doubleValue()</code>).
   *
   * @param number
   * @return java.lang.Double
   */
  public static Double toDouble(Number number) {
    return number == null || number instanceof Double ? (Double)number : new Double(number.doubleValue());
  }
  /**
   * Converts the given number to a <code>java.math.BigInteger</code>.
   *
   * @param number
   * @return java.math.BigInteger
   * @throws IllegalArgumentException The given number is "not a number" or infinite.
   */
  public static BigInteger toBigInteger(Number number) throws IllegalArgumentException {
    if (number == null || number instanceof BigInteger)
      return (BigInteger)number;
    if (number instanceof BigDecimal)
      return ((BigDecimal)number).toBigInteger();
    if (isDoubleCompatible(number)) {
      if (isNaN(number) || isInfinite(number))
        throw new IllegalArgumentException("Argument must not be NaN or infinite.");
      return new BigDecimal(number.toString()).toBigInteger();
    } // => isLongCompatible(number) or unknown Number type
    return BigInteger.valueOf(number.longValue());
  }
  /**
   * Converts the given number to a <code>java.math.BigDecimal</code>.
   *
   * @param number
   * @return java.math.BigDecimal
   * @throws IllegalArgumentException The given number is "not a number" or infinite.
   */
  public static BigDecimal toBigDecimal(Number number) throws IllegalArgumentException {
    if (number == null || number instanceof BigDecimal)
      return (BigDecimal)number;
    if (number instanceof BigInteger)
      return new BigDecimal((BigInteger)number);
    if (isDoubleCompatible(number)) {
      if (isNaN(number) || isInfinite(number))
        throw new IllegalArgumentException("Argument must not be NaN or infinite.");
      return new BigDecimal(number.toString());
    }
    if (isLongCompatible(number))
      return BigDecimal.valueOf(number.longValue());
    // => unknown Number type
    return new BigDecimal(String.valueOf(number.doubleValue()));
  }
  /**
   * Compares the first number to the second one numerically and 
   * returns an integer depending on the comparison result:
   * a negative value if the first number is the smaller one,
   * a zero value if they are equal, and
   * a positive value if the first number is the larger one.
   *
   * The main strategy goes like follows:
   * 1. If one of the arguments is <code>null</code> or "not a number",
   *    throw an exception.
   * 2. If both values are "long compatible", compare their <code>longValue()</code>
   *    using the usual comparison operators for primitive types (&lt;, ==, &gt;).
   * 3. If both values are "double compatible", compare their <code>doubleValue()</code>
   *    using the usual comparison operators for primitive types (&lt;, ==, &gt;).
   * 4. If one of the values is infinite (and the other is finite),
   *    determine the result depending on the sign of the infinite value.
   * 5. Otherwise convert both values to <code>java.math.BigDecimal</code> and
   *    return the result of the <code>BigDecimal.rupareTo(BigDecimal)</code> method.
   *
   * As a consequence, the method is not suitable to implement a
   * <code>java.util.ruparator</code> for numbers. To achieve this,
   * one had to accept "not a number" arguments and place them somewhere
   * in the row of numbers (probably at the upper end, i.e. larger than
   * positive infinity, as <code>Double.rupare(double, double)</code>
   * does it).
   * So the behavior of this method is like that of the comparison
   * operator for primitive types and not like that of the related
   * <code>compareTo(...)</code> methods. Besides the handling of
   * "not a number" values this makes a difference, when comparing
   * the float or double values <code>-0.0</code> and <code>0.0</code>:
   * again, like the operators, we consider them as equal (whereas
   * according to <code>Double.rupareTo(...)</code> <code>-0.0</code>
   * is less than <code>0.0</code>).
   *
   * @param first
   * @param second
   * @return int
   * @throws ArithmeticException One or both of the given numbers is <code>null</code> or "not a number".
   */
  public static int compare(Number first, Number second) throws ArithmeticException {
    if (first == null || second == null || isNaN(first) || isNaN(second))
      throw new ArithmeticException("Arguments must not be null or NaN.");
    int result = -2;
    if (isLongCompatible(first) && isLongCompatible(second)) {
      long v1 = first.longValue(), v2 = second.longValue();
      result = v1 < v2 ? -1 : v1 == v2 ? 0 : v1 > v2 ? 1 : 2;
    } else if (isDoubleCompatible(first) && isDoubleCompatible(second)) {
      double v1 = first.doubleValue(), v2 = second.doubleValue();
      result = v1 < v2 ? -1 : v1 == v2 ? 0 : v1 > v2 ? 1 : 2;
    }
    if (result == 2)    // should not happen
      throw new ArithmeticException("Arguments " + first + " and " + second + " are not comparable.");
    if (result > -2)
      return result;
    if (isInfinite(first))    // => second is finite
      return first.doubleValue() == Double.NEGATIVE_INFINITY ? -1 : 1;
    if (isInfinite(second))   // => first is finite
      return second.doubleValue() == Double.POSITIVE_INFINITY ? -1 : 1;
    return toBigDecimal(first).rupareTo(toBigDecimal(second));
  }
}





Checks whether the String a valid Java number.

  
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */
import java.math.BigDecimal;
import java.math.BigInteger;
public final class NumberUtils {

    // Empty checks
    //-----------------------------------------------------------------------
    /**
     * <p>Checks if a String is empty ("") or null.</p>
     *
     * <pre>
     * StringUtils.isEmpty(null)      = true
     * StringUtils.isEmpty("")        = true
     * StringUtils.isEmpty(" ")       = false
     * StringUtils.isEmpty("bob")     = false
     * StringUtils.isEmpty("  bob  ") = false
     * </pre>
     *
     * <p>NOTE: This method changed in Lang version 2.0.
     * It no longer trims the String.
     * That functionality is available in isBlank().</p>
     *
     * @param str  the String to check, may be null
     * @return <code>true</code> if the String is empty or null
     */
    public static boolean isEmpty(String str) {
        return str == null || str.length() == 0;
    }
    /**
     * <p>Checks whether the String a valid Java number.</p>
     *
     * <p>Valid numbers include hexadecimal marked with the <code>0x</code>
     * qualifier, scientific notation and numbers marked with a type
     * qualifier (e.g. 123L).</p>
     *
     * <p><code>Null</code> and empty String will return
     * <code>false</code>.</p>
     *
     * @param str  the <code>String</code> to check
     * @return <code>true</code> if the string is a correctly formatted number
     */
    public static boolean isNumber(String str) {
        if (isEmpty(str)) {
            return false;
        }
        char[] chars = str.toCharArray();
        int sz = chars.length;
        boolean hasExp = false;
        boolean hasDecPoint = false;
        boolean allowSigns = false;
        boolean foundDigit = false;
        // deal with any possible sign up front
        int start = (chars[0] == "-") ? 1 : 0;
        if (sz > start + 1) {
            if (chars[start] == "0" && chars[start + 1] == "x") {
                int i = start + 2;
                if (i == sz) {
                    return false; // str == "0x"
                }
                // checking hex (it can"t be anything else)
                for (; i < chars.length; i++) {
                    if ((chars[i] < "0" || chars[i] > "9")
                        && (chars[i] < "a" || chars[i] > "f")
                        && (chars[i] < "A" || chars[i] > "F")) {
                        return false;
                    }
                }
                return true;
            }
        }
        sz--; // don"t want to loop to the last char, check it afterwords
              // for type qualifiers
        int i = start;
        // loop to the next to last char or to the last char if we need another digit to
        // make a valid number (e.g. chars[0..5] = "1234E")
        while (i < sz || (i < sz + 1 && allowSigns && !foundDigit)) {
            if (chars[i] >= "0" && chars[i] <= "9") {
                foundDigit = true;
                allowSigns = false;
            } else if (chars[i] == ".") {
                if (hasDecPoint || hasExp) {
                    // two decimal points or dec in exponent   
                    return false;
                }
                hasDecPoint = true;
            } else if (chars[i] == "e" || chars[i] == "E") {
                // we"ve already taken care of hex.
                if (hasExp) {
                    // two E"s
                    return false;
                }
                if (!foundDigit) {
                    return false;
                }
                hasExp = true;
                allowSigns = true;
            } else if (chars[i] == "+" || chars[i] == "-") {
                if (!allowSigns) {
                    return false;
                }
                allowSigns = false;
                foundDigit = false; // we need a digit after the E
            } else {
                return false;
            }
            i++;
        }
        if (i < chars.length) {
            if (chars[i] >= "0" && chars[i] <= "9") {
                // no type qualifier, OK
                return true;
            }
            if (chars[i] == "e" || chars[i] == "E") {
                // can"t have an E at the last byte
                return false;
            }
            if (!allowSigns
                && (chars[i] == "d"
                    || chars[i] == "D"
                    || chars[i] == "f"
                    || chars[i] == "F")) {
                return foundDigit;
            }
            if (chars[i] == "l"
                || chars[i] == "L") {
                // not allowing L with an exponent
                return foundDigit && !hasExp;
            }
            // last character is illegal
            return false;
        }
        // allowSigns is true iff the val ends in "E"
        // found digit it to make sure weird stuff like "." and "1E-" doesn"t pass
        return !allowSigns && foundDigit;
    }
}





Convert to numbers

   
/*
 * Copyright Javelin Software, All rights reserved.
 */

import java.math.*;
/**
 * The NumberUtil is used as a Utility Class for Numbers
 * classes such as Integers and Doubles etc.
 * 
 * @author Robin Sharp
 */
public class NumberUtil 
{
    /**
     * Returns the BigDecimal value n with trailing
     * zeroes removed.
     */
    public static BigDecimal trim(BigDecimal n) 
    {
        try
        {
            while (true) 
            {
                n = n.setScale(n.scale()-1);
            }
        }
        catch (ArithmeticException e)
        {
            // no more trailing zeroes so exit.
        }
        return n;
    }
    /**
     * Returns the BigDecimal value n with exactly
     * "prec" decimal places.
     * Zeroes are padded to the right of the decimal
     * point if necessary.
     */
    public static BigDecimal format(BigDecimal n, int prec) 
    {
        return n.setScale(prec, BigDecimal.ROUND_HALF_UP);
    }
    
    /**
     * Convert an Object of type Class to a Number.
     */
    public static Object toObject( Class clazz, Object value )
    {
        if( value == null ) return null;
        if( clazz == null ) return value;
        
        if( Boolean.class.isAssignableFrom( clazz ) ) return toBoolean( value );
        if( Byte.class.isAssignableFrom( clazz ) ) return toByte( value );
        if( Short.class.isAssignableFrom( clazz ) ) return toShort( value );
        if( Integer.class.isAssignableFrom( clazz ) ) return toInteger( value );
        if( Long.class.isAssignableFrom( clazz ) ) return toLong( value );
        if( Float.class.isAssignableFrom( clazz ) ) return toFloat( value );
        if( Double.class.isAssignableFrom( clazz ) ) return toDouble( value );
        if( BigInteger.class.isAssignableFrom( clazz ) ) return toBigInteger( value );
        if( BigDecimal.class.isAssignableFrom( clazz ) ) return toBigDecimal( value );
        
        return value;
    }
    
    /**
     * Convert a Sting "TRUE" to 1, otherwise 0.
     */
    public static int valueOfBoolean( String string )
    {
        return string != null && "TRUE".equalsIgnoreCase( string ) ? 1 : 0;
    }
    
    /**
     * Optimisation Code
     */
    public static Boolean getBoolean( boolean bool )
    {
        return bool ? Boolean.TRUE : Boolean.FALSE;
    }
    
    /**
     * Convert an Object to a  Boolean.
     */
    public static Boolean toBoolean( Object value )
    {
        if( value == null ) return null;        
        if( value instanceof Boolean ) return (Boolean)value;
        
        if( "TRUE".equalsIgnoreCase( value.toString() ) ) return Boolean.TRUE;
        if( "".equals( value.toString() ) ) return null;
        
        return Boolean.FALSE;
    }
    
    /**
     * Convert an Object to an Integer.
     */
    public static Integer toInteger( Object value )
    {
        if( value == null ) return null;        
        if( value instanceof Integer ) return (Integer)value;
        if( value instanceof String )
        {
            if( "".equals( (String)value ) ) return null;
            return new Integer( (String)value );
        }
        
        if( value instanceof Number ) return new Integer( ((Number)value).intValue() );
        
        return new Integer( value.toString() );
    }
    
    /**
     * Convert an Object to a Long.
     */
    public static Long toLong( Object value )
    {
        if( value == null ) return null;        
        if( value instanceof Long ) return (Long)value;
        if( value instanceof String )
        {
            if( "".equals( (String)value ) ) return null;
            return new Long( (String)value );
        }
        if( value instanceof Number ) return new Long( ((Number)value).shortValue() );
        
        return new Long( value.toString() );
    }
    /**
     * Convert an Object to a Short.
     */
    public static Short toShort( Object value )
    {
        if( value == null ) return null;        
        if( value instanceof Short ) return (Short)value;
        if( value instanceof String )
        {
            if( "".equals( (String)value ) ) return null;
            return new Short( (String)value );
        }
        if( value instanceof Number ) return new Short( ((Number)value).shortValue() );
        
        return new Short( value.toString() );
    }
    
    /**
     * Convert an Object to a Byte.
     */
    public static Byte toByte( Object value )
    {
        if( value == null ) return null;        
        if( value instanceof Byte ) return (Byte)value;
        if( value instanceof String )
        {
            if( "".equals( (String)value ) ) return null;
            return new Byte( (String)value );
        }
        if( value instanceof Number ) return new Byte( ((Number)value).byteValue() );
        
        return new Byte( value.toString() );
    }
    
    /**
     * Convert an Object to a Float.
     */
    public static Float toFloat( Object value )
    {
        if( value == null ) return null;        
        if( value instanceof Float ) return (Float)value;
        if( value instanceof String )
        {
            if( "".equals( (String)value ) ) return null;
            return new Float( (String)value );
        }
        if( value instanceof Number ) return new Float( ((Number)value).floatValue() );
        
        return new Float( value.toString() );
    }
    
    /**
     * Convert an Object to a Double.
     */
    public static Double toDouble( Object value )
    {
        if( value == null ) return null;        
        if( value instanceof Double ) return (Double)value;
        if( value instanceof String )
        {
            if( "".equals( (String)value ) ) return null;
            return new Double( (String)value );
        }
        if( value instanceof Number ) return new Double( ((Number)value).doubleValue() );
        
        return new Double( value.toString() );
    }
    
    /**
     * Convert an Object to a BigInteger.
     */
    public static BigInteger toBigInteger( Object value )
    {
        if( value == null ) return null;        
        if( value instanceof BigInteger ) return (BigInteger)value;
        if( value instanceof String )
        {
            if( "".equals( (String)value ) ) return null;
            return new BigInteger( (String)value );
        }
        
        return new BigInteger( value.toString() );
    }
    
    /**
     * Convert an Object to a BigDecimal.
     */
    public static BigDecimal toBigDecimal( Object value )
    {
        if( value == null ) return null;        
        if( value instanceof BigDecimal ) return (BigDecimal)value;
        if( value instanceof String )
        {
            if( "".equals( (String)value ) ) return null;
            return new BigDecimal( (String)value );
        }
        if( value instanceof Number ) return new BigDecimal( ((Number)value).doubleValue() );
        
        return new BigDecimal( value.toString() );
    }
    /**
     * Convert an Object to a Boolean.
     */
    public static boolean booleanValue( Object value )
    {
        if( value == null ) return false;        
        if( value instanceof Boolean ) return ((Boolean)value).booleanValue();
        if( value instanceof Number ) return ((Number)value).intValue() != 0;        
        return "TRUE".equalsIgnoreCase( value.toString() );
    }
    
    /**
     * Convert an Object to an int, or 0 if it is null.
     */
    public static int intValue( Object value )
    {
        if( value == null ) return 0;
        return toInteger( value ).intValue();
    }
    
    /**
     * Convert an Object to a long, or 0 if it is null.
     */
    public static long longValue( Object value )
    {
        if( value == null ) return 0L;
        return toLong( value ).longValue();
    }
    /**
     * Convert an Object to a short, or 0 if it is null.
     */
    public static short shortValue( Object value )
    {
        if( value == null ) return 0;
        return toShort( value ).shortValue();
    }
   /**
    * Convert an Object to a byte, or 0 if it is null.
    */
    public static byte byteValue( Object value )
    {
        if( value == null ) return 0;
        return toByte( value ).byteValue();
    }
    
   /**
    * Convert an Object to a float, or 0 if it is null.
    */
    public static float floatValue( Object value )
    {
        if( value == null ) return 0.0f;
        return toFloat( value ).floatValue();
    }
    
   /**
    * Convert an Object to a double, or 0 if it is null.
    */
    public static double doubleValue( Object value )
    {
        if( value == null ) return 0.0;
        return toDouble( value ).doubleValue();
    }
 }





Get Digit Number String

   
/*
 * Copyright (c) 2003 - 2007 OpenSubsystems s.r.o. Slovak Republic. All rights reserved.
 * 
 * Project: OpenSubsystems
 * 
 * $Id: NumberUtils.java,v 1.9 2007/01/07 06:14:01 bastafidli Exp $
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License. 
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */
import java.text.NumberFormat;
/**
 * Collection of useful utilities to work with numbers. 
 * 
 * @version $Id: NumberUtils.java,v 1.9 2007/01/07 06:14:01 bastafidli Exp $
 * @author Peter Satury
 * @code.reviewer Miro Halas
 * @code.reviewed Initial revision
 */
public final class NumberUtils
{
   // Constants ////////////////////////////////////////////////////////////////
   
   /**
    * Static array used to append leading 0 chars to file name constructed from
    * number.
    */
   protected static final char[] ZEROCHARS = {"0", "0", "0", "0", "0", "0", "0", "0", "0", "0",
                                              "0", "0", "0", "0", "0", "0", "0", "0", "0", "0",
                                              "0", "0", "0", "0", "0", "0", "0", "0", "0", "0",
                                              "0", "0", "0", "0", "0", "0", "0", "0", "0", "0",
                                              "0", "0", "0", "0", "0", "0", "0", "0", "0", "0",
                                             };
   // Cached values ////////////////////////////////////////////////////////////
   
   /**
    * static Number format for no Exponent 
    */
   public static final NumberFormat NFFORMAT;
   
   /**
    * static Number format for no Exponent for editing
    */
   public static final NumberFormat NFFORMATEDIT;
   /**
    * static Number format for Currency
    */
   public static final NumberFormat NFCURRENCYFORMAT;
   /**
    * static Number format for Currency for editing
    */
   public static final NumberFormat NFCURRENCYFORMATEDIT;
   // Constructors /////////////////////////////////////////////////////////////
   
   /**
    * Static initializer.
    */
   static
   {
      
      NFFORMAT = NumberFormat.getNumberInstance();
      NFFORMAT.setMaximumFractionDigits(20);
      
      NFFORMATEDIT = NumberFormat.getNumberInstance();
      NFFORMATEDIT.setMaximumFractionDigits(20);
      NFFORMATEDIT.setGroupingUsed(false);
      NFCURRENCYFORMAT = NumberFormat.getNumberInstance();
      NFCURRENCYFORMAT.setMaximumFractionDigits(2);
      NFCURRENCYFORMAT.setMinimumFractionDigits(2);
      NFCURRENCYFORMATEDIT = NumberFormat.getNumberInstance();
      NFCURRENCYFORMATEDIT.setMaximumFractionDigits(2);
      NFCURRENCYFORMATEDIT.setMinimumFractionDigits(2);
      NFCURRENCYFORMATEDIT.setGroupingUsed(false);
   }
   /** 
    * Private constructor since this class cannot be instantiated
    */
   private NumberUtils(
   )
   {
      // Do nothing
   }
   // Public methods ///////////////////////////////////////////////////////////
   
   /**
    * Method to make Exponention
    * 
    * @param iBbase - base of Exponention [1..]
    * @param iExponent - exponent of Exponention [0..14]
    * @return long - result of Exponention
    * @throws IllegalArgumentException - in case of arguments out of valid range
    */
   public static long exponentiate(
      int iBbase, 
      int iExponent
   ) throws IllegalArgumentException
   {
      if (iExponent > 14 || iExponent < 0)
      {
         throw new IllegalArgumentException(
               "Exponent could not be greater then 14 and lower then 0");
      }
      if (iBbase < 1)
      {
         throw new IllegalArgumentException(
               "Exponentiate base could not be lower then 1");
      }
      long lReturn = 1;
      for (int iCounter = 0; iCounter < iExponent; iCounter++)
      {
         try
         {
            lReturn = lReturn * iBbase;
         } 
         catch (Exception eExc)
         {
            throw new IllegalArgumentException(
                  "Exponentiate arguments too high");
         }
      }
      return lReturn;
   }
   /**
    * Method to make specified length digit number string representation from particular 
    * input number.
    * For example, if there will be send input number 32 and digit lenhth = 8, output 
    * will be string "00000032"
    * 
    * @param iInputNumber - input number that will be converted into 8 digit number 
    *                       string representation
    * @param iDigitLength - length of the output digit number string
    * 
    * @return String - digit number string representation
    */
   public static String getDigitNumberString(
      int iInputNumber,
      int iDigitLength
   )
   {
      StringBuffer idString = new StringBuffer(Integer.toString(iInputNumber));
      
      if (iDigitLength - idString.length() > 0)
      {
         idString.insert(0, ZEROCHARS, 0, iDigitLength - idString.length());
      }
      return idString.toString();
   }
}





Methods for number conversion and parsing

   
/*
 * Copyright 2002-2006 the original author or 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.
 */

import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.NumberFormat;
import java.text.ParseException;
/**
 * Miscellaneous utility methods for number conversion and parsing.
 * Mainly for internal use within the framework; consider Jakarta"s
 * Commons Lang for a more comprehensive suite of string utilities.
 *
 * @author Juergen Hoeller
 * @author Rob Harrop
 * @since 1.1.2
 */
public abstract class NumberUtils {
  /**
   * Convert the given number into an instance of the given target class.
   * @param number the number to convert
   * @param targetClass the target class to convert to
   * @return the converted number
   * @throws IllegalArgumentException if the target class is not supported
   * (i.e. not a standard Number subclass as included in the JDK)
   * @see java.lang.Byte
   * @see java.lang.Short
   * @see java.lang.Integer
   * @see java.lang.Long
   * @see java.math.BigInteger
   * @see java.lang.Float
   * @see java.lang.Double
   * @see java.math.BigDecimal
   */
  public static Number convertNumberToTargetClass(Number number, Class targetClass)
      throws IllegalArgumentException {

    if (targetClass.isInstance(number)) {
      return number;
    }
    else if (targetClass.equals(Byte.class)) {
      long value = number.longValue();
      if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) {
        raiseOverflowException(number, targetClass);
      }
      return new Byte(number.byteValue());
    }
    else if (targetClass.equals(Short.class)) {
      long value = number.longValue();
      if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) {
        raiseOverflowException(number, targetClass);
      }
      return new Short(number.shortValue());
    }
    else if (targetClass.equals(Integer.class)) {
      long value = number.longValue();
      if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) {
        raiseOverflowException(number, targetClass);
      }
      return new Integer(number.intValue());
    }
    else if (targetClass.equals(Long.class)) {
      return new Long(number.longValue());
    }
    else if (targetClass.equals(Float.class)) {
      return new Float(number.floatValue());
    }
    else if (targetClass.equals(Double.class)) {
      return new Double(number.doubleValue());
    }
    else if (targetClass.equals(BigInteger.class)) {
      return BigInteger.valueOf(number.longValue());
    }
    else if (targetClass.equals(BigDecimal.class)) {
      // using BigDecimal(String) here, to avoid unpredictability of BigDecimal(double)
      // (see BigDecimal javadoc for details)
      return new BigDecimal(number.toString());
    }
    else {
      throw new IllegalArgumentException("Could not convert number [" + number + "] of type [" +
          number.getClass().getName() + "] to unknown target class [" + targetClass.getName() + "]");
    }
  }
  /**
   * Raise an overflow exception for the given number and target class.
   * @param number the number we tried to convert
   * @param targetClass the target class we tried to convert to
   */
  private static void raiseOverflowException(Number number, Class targetClass) {
    throw new IllegalArgumentException("Could not convert number [" + number + "] of type [" +
        number.getClass().getName() + "] to target class [" + targetClass.getName() + "]: overflow");
  }
  /**
   * Parse the given text into a number instance of the given target class,
   * using the corresponding default <code>decode</code> methods. Trims the
   * input <code>String</code> before attempting to parse the number. Supports
   * numbers in hex format (with leading 0x) and in octal format (with leading 0).
   * @param text the text to convert
   * @param targetClass the target class to parse into
   * @return the parsed number
   * @throws IllegalArgumentException if the target class is not supported
   * (i.e. not a standard Number subclass as included in the JDK)
   * @see java.lang.Byte#decode
   * @see java.lang.Short#decode
   * @see java.lang.Integer#decode
   * @see java.lang.Long#decode
   * @see #decodeBigInteger(String)
   * @see java.lang.Float#valueOf
   * @see java.lang.Double#valueOf
   * @see java.math.BigDecimal#BigDecimal(String)
   */
  public static Number parseNumber(String text, Class targetClass) {

    String trimmed = text.trim();
    if (targetClass.equals(Byte.class)) {
      return Byte.decode(trimmed);
    }
    else if (targetClass.equals(Short.class)) {
      return Short.decode(trimmed);
    }
    else if (targetClass.equals(Integer.class)) {
      return Integer.decode(trimmed);
    }
    else if (targetClass.equals(Long.class)) {
      return Long.decode(trimmed);
    }
    else if (targetClass.equals(BigInteger.class)) {
      return decodeBigInteger(trimmed);
    }
    else if (targetClass.equals(Float.class)) {
      return Float.valueOf(trimmed);
    }
    else if (targetClass.equals(Double.class)) {
      return Double.valueOf(trimmed);
    }
    else if (targetClass.equals(BigDecimal.class) || targetClass.equals(Number.class)) {
      return new BigDecimal(trimmed);
    }
    else {
      throw new IllegalArgumentException(
          "Cannot convert String [" + text + "] to target class [" + targetClass.getName() + "]");
    }
  }
  /**
   * Parse the given text into a number instance of the given target class,
   * using the given NumberFormat. Trims the input <code>String</code>
   * before attempting to parse the number.
   * @param text the text to convert
   * @param targetClass the target class to parse into
   * @param numberFormat the NumberFormat to use for parsing (if <code>null</code>,
   * this method falls back to <code>parseNumber(String, Class)</code>)
   * @return the parsed number
   * @throws IllegalArgumentException if the target class is not supported
   * (i.e. not a standard Number subclass as included in the JDK)
   * @see java.text.NumberFormat#parse
   * @see #convertNumberToTargetClass
   * @see #parseNumber(String, Class)
   */
  public static Number parseNumber(String text, Class targetClass, NumberFormat numberFormat) {
    if (numberFormat != null) {
      try {
        Number number = numberFormat.parse(text.trim());
        return convertNumberToTargetClass(number, targetClass);
      }
      catch (ParseException ex) {
        throw new IllegalArgumentException(ex.getMessage());
      }
    }
    else {
      return parseNumber(text, targetClass);
    }
  }
  /**
   * Decode a {@link java.math.BigInteger} from a {@link String} value.
   * Supports decimal, hex and octal notation.
   * @see BigInteger#BigInteger(String, int)
   */
  private static BigInteger decodeBigInteger(String value) {
    int radix = 10;
    int index = 0;
    boolean negative = false;
    // Handle minus sign, if present.
    if (value.startsWith("-")) {
      negative = true;
      index++;
    }
    // Handle radix specifier, if present.
    if (value.startsWith("0x", index) || value.startsWith("0X", index)) {
      index += 2;
      radix = 16;
    }
    else if (value.startsWith("#", index)) {
      index++;
      radix = 16;
    }
    else if (value.startsWith("0", index) && value.length() > 1 + index) {
      index++;
      radix = 8;
    }
    BigInteger result = new BigInteger(value.substring(index), radix);
    return (negative ? result.negate() : result);
  }
}





Provides IEEE-754r variants of NumberUtils methods.

   
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */
/**
 * <p>Provides IEEE-754r variants of NumberUtils methods. </p>
 *
 * <p>See: </p>
 *
 * @since 2.4
 * @version $Id: IEEE754rUtils.java 634088 2008-03-06 00:06:05Z niallp $
 */
public class IEEE754rUtils {
    
     /**
     * <p>Returns the minimum value in an array.</p>
     * 
     * @param array  an array, must not be null or empty
     * @return the minimum value in the array
     * @throws IllegalArgumentException if <code>array</code> is <code>null</code>
     * @throws IllegalArgumentException if <code>array</code> is empty
     */
    public static double min(double[] array) {
        // Validates input
        if (array == null) {
            throw new IllegalArgumentException("The Array must not be null");
        } else if (array.length == 0) {
            throw new IllegalArgumentException("Array cannot be empty.");
        }
    
        // Finds and returns min
        double min = array[0];
        for (int i = 1; i < array.length; i++) {
            min = min(array[i], min);
        }
    
        return min;
    }
    /**
     * <p>Returns the minimum value in an array.</p>
     * 
     * @param array  an array, must not be null or empty
     * @return the minimum value in the array
     * @throws IllegalArgumentException if <code>array</code> is <code>null</code>
     * @throws IllegalArgumentException if <code>array</code> is empty
     */
    public static float min(float[] array) {
        // Validates input
        if (array == null) {
            throw new IllegalArgumentException("The Array must not be null");
        } else if (array.length == 0) {
            throw new IllegalArgumentException("Array cannot be empty.");
        }
    
        // Finds and returns min
        float min = array[0];
        for (int i = 1; i < array.length; i++) {
            min = min(array[i], min);
        }
    
        return min;
    }
    /**
     * <p>Gets the minimum of three <code>double</code> values.</p>
     * 
     * <p>NaN is only returned if all numbers are NaN as per IEEE-754r. </p>
     * 
     * @param a  value 1
     * @param b  value 2
     * @param c  value 3
     * @return  the smallest of the values
     */
    public static double min(double a, double b, double c) {
        return min(min(a, b), c);
    }
    /**
     * <p>Gets the minimum of two <code>double</code> values.</p>
     * 
     * <p>NaN is only returned if all numbers are NaN as per IEEE-754r. </p>
     * 
     * @param a  value 1
     * @param b  value 2
     * @return  the smallest of the values
     */
    public static double min(double a, double b) {
        if(Double.isNaN(a)) {
            return b;
        } else
        if(Double.isNaN(b)) {
            return a;
        } else {
            return Math.min(a, b);
        }
    }
    /**
     * <p>Gets the minimum of three <code>float</code> values.</p>
     * 
     * <p>NaN is only returned if all numbers are NaN as per IEEE-754r. </p>
     *
     * @param a  value 1
     * @param b  value 2
     * @param c  value 3
     * @return  the smallest of the values
     */
    public static float min(float a, float b, float c) {
        return min(min(a, b), c);
    }
    /**
     * <p>Gets the minimum of two <code>float</code> values.</p>
     * 
     * <p>NaN is only returned if all numbers are NaN as per IEEE-754r. </p>
     *
     * @param a  value 1
     * @param b  value 2
     * @return  the smallest of the values
     */
    public static float min(float a, float b) {
        if(Float.isNaN(a)) {
            return b;
        } else
        if(Float.isNaN(b)) {
            return a;
        } else {
            return Math.min(a, b);
        }
    }
    /**
     * <p>Returns the maximum value in an array.</p>
     * 
     * @param array  an array, must not be null or empty
     * @return the minimum value in the array
     * @throws IllegalArgumentException if <code>array</code> is <code>null</code>
     * @throws IllegalArgumentException if <code>array</code> is empty
     */
    public static double max(double[] array) {
        // Validates input
        if (array== null) {
            throw new IllegalArgumentException("The Array must not be null");
        } else if (array.length == 0) {
            throw new IllegalArgumentException("Array cannot be empty.");
        }
    
        // Finds and returns max
        double max = array[0];
        for (int j = 1; j < array.length; j++) {
            max = max(array[j], max);
        }
    
        return max;
    }
    /**
     * <p>Returns the maximum value in an array.</p>
     * 
     * @param array  an array, must not be null or empty
     * @return the minimum value in the array
     * @throws IllegalArgumentException if <code>array</code> is <code>null</code>
     * @throws IllegalArgumentException if <code>array</code> is empty
     */
    public static float max(float[] array) {
        // Validates input
        if (array == null) {
            throw new IllegalArgumentException("The Array must not be null");
        } else if (array.length == 0) {
            throw new IllegalArgumentException("Array cannot be empty.");
        }
        // Finds and returns max
        float max = array[0];
        for (int j = 1; j < array.length; j++) {
            max = max(array[j], max);
        }
        return max;
    }
     
    /**
     * <p>Gets the maximum of three <code>double</code> values.</p>
     * 
     * <p>NaN is only returned if all numbers are NaN as per IEEE-754r. </p>
     *
     * @param a  value 1
     * @param b  value 2
     * @param c  value 3
     * @return  the largest of the values
     */
    public static double max(double a, double b, double c) {
        return max(max(a, b), c);
    }
    /**
     * <p>Gets the maximum of two <code>double</code> values.</p>
     * 
     * <p>NaN is only returned if all numbers are NaN as per IEEE-754r. </p>
     *
     * @param a  value 1
     * @param b  value 2
     * @return  the largest of the values
     */
    public static double max(double a, double b) {
        if(Double.isNaN(a)) {
            return b;
        } else
        if(Double.isNaN(b)) {
            return a;
        } else {
            return Math.max(a, b);
        }
    }
    /**
     * <p>Gets the maximum of three <code>float</code> values.</p>
     * 
     * <p>NaN is only returned if all numbers are NaN as per IEEE-754r. </p>
     *
     * @param a  value 1
     * @param b  value 2
     * @param c  value 3
     * @return  the largest of the values
     */
    public static float max(float a, float b, float c) {
        return max(max(a, b), c);
    }
    /**
     * <p>Gets the maximum of two <code>float</code> values.</p>
     * 
     * <p>NaN is only returned if all numbers are NaN as per IEEE-754r. </p>
     *
     * @param a  value 1
     * @param b  value 2
     * @return  the largest of the values
     */
    public static float max(float a, float b) {
        if(Float.isNaN(a)) {
            return b;
        } else
        if(Float.isNaN(b)) {
            return a;
        } else {
            return Math.max(a, b);
        }
    }
}





Turns a string value into a java.lang.Number.

   
import java.math.BigDecimal;
import java.math.BigInteger;
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */

/**
 * Contains useful helper methods for classes within this package.
 *
 * @author John Keyes (john at integralsource.ru)
 * @version $Revision: 680644 $, $Date: 2008-07-29 01:13:48 -0700 (Tue, 29 Jul 2008) $
 */
public class Main {

  //--------------------------------------------------------------------
  
  // must handle Long, Float, Integer, Float, Short,
  //                  BigDecimal, BigInteger and Byte
  // useful methods:
  // Byte.decode(String)
  // Byte.valueOf(String,int radix)
  // Byte.valueOf(String)
  // Double.valueOf(String)
  // Float.valueOf(String)
  // new Float(String)
  // Integer.valueOf(String,int radix)
  // Integer.valueOf(String)
  // Integer.decode(String)
  // Integer.getInteger(String)
  // Integer.getInteger(String,int val)
  // Integer.getInteger(String,Integer val)
  // new Integer(String)
  // new Double(String)
  // new Byte(String)
  // new Long(String)
  // Long.getLong(String)
  // Long.getLong(String,int)
  // Long.getLong(String,Integer)
  // Long.valueOf(String,int)
  // Long.valueOf(String)
  // new Short(String)
  // Short.decode(String)
  // Short.valueOf(String,int)
  // Short.valueOf(String)
  // new BigDecimal(String)
  // new BigInteger(String)
  // new BigInteger(String,int radix)
  // Possible inputs:
  // 45 45.5 45E7 4.5E7 Hex Oct Binary xxxF xxxD xxxf xxxd
  // plus minus everything. Prolly more. A lot are not separable.
  /**
   * <p>Turns a string value into a java.lang.Number.</p>
   *
   * <p>First, the value is examined for a type qualifier on the end
   * (<code>"f","F","d","D","l","L"</code>).  If it is found, it starts 
   * trying to create successively larger types from the type specified
   * until one is found that can hold the value.</p>
   *
   * <p>If a type specifier is not found, it will check for a decimal point
   * and then try successively larger types from <code>Integer</code> to
   * <code>BigInteger</code> and from <code>Float</code> to
   * <code>BigDecimal</code>.</p>
   *
   * <p>If the string starts with <code>0x</code> or <code>-0x</code>, it
   * will be interpreted as a hexadecimal integer.  Values with leading
   * <code>0</code>"s will not be interpreted as octal.</p>
   *
   * @param val String containing a number
   * @return Number created from the string
   * @throws NumberFormatException if the value cannot be converted
   */
  public static Number createNumber(String val) throws NumberFormatException {
      if (val == null) {
          return null;
      }
      if (val.length() == 0) {
          throw new NumberFormatException("\"\" is not a valid number.");
      }
      if (val.startsWith("--")) {
          // this is protection for poorness in java.lang.BigDecimal.
          // it accepts this as a legal value, but it does not appear 
          // to be in specification of class. OS X Java parses it to 
          // a wrong value.
          return null;
      }
      if (val.startsWith("0x") || val.startsWith("-0x")) {
          return createInteger(val);
      }   
      char lastChar = val.charAt(val.length() - 1);
      String mant;
      String dec;
      String exp;
      int decPos = val.indexOf(".");
      int expPos = val.indexOf("e") + val.indexOf("E") + 1;
      if (decPos > -1) {
          if (expPos > -1) {
              if (expPos < decPos) {
                  throw new NumberFormatException(val + " is not a valid number.");
              }
              dec = val.substring(decPos + 1, expPos);
          } else {
              dec = val.substring(decPos + 1);
          }
          mant = val.substring(0, decPos);
      } else {
          if (expPos > -1) {
              mant = val.substring(0, expPos);
          } else {
              mant = val;
          }
          dec = null;
      }
      if (!Character.isDigit(lastChar)) {
          if (expPos > -1 && expPos < val.length() - 1) {
              exp = val.substring(expPos + 1, val.length() - 1);
          } else {
              exp = null;
          }
          //Requesting a specific type..
          String numeric = val.substring(0, val.length() - 1);
          boolean allZeros = isAllZeros(mant) && isAllZeros(exp);
          switch (lastChar) {
              case "l" :
              case "L" :
                  if (dec == null
                      && exp == null
                      && (numeric.charAt(0) == "-" && isDigits(numeric.substring(1)) || isDigits(numeric))) {
                      try {
                          return createLong(numeric);
                      } catch (NumberFormatException nfe) {
                          //Too big for a long
                      }
                      return createBigInteger(numeric);
                  }
                  throw new NumberFormatException(val + " is not a valid number.");
              case "f" :
              case "F" :
                  try {
                      Float f = createFloat(numeric);
                      if (!(f.isInfinite() || (f.floatValue() == 0.0F && !allZeros))) {
                          //If it"s too big for a float or the float value = 0 and the string
                          //has non-zeros in it, then float does not have the precision we want
                          return f;
                      }
                  } catch (NumberFormatException e) {
                      // ignore the bad number
                  }
                  //Fall through
              case "d" :
              case "D" :
                  try {
                      Double d = createDouble(numeric);
                      if (!(d.isInfinite() || (d.floatValue() == 0.0D && !allZeros))) {
                          return d;
                      }
                  } catch (NumberFormatException nfe) {
                      // empty catch
                  }
                  try {
                      return createBigDecimal(numeric);
                  } catch (NumberFormatException e) {
                      // empty catch
                  }
                  //Fall through
              default :
                  throw new NumberFormatException(val + " is not a valid number.");
          }
      } else {
          //User doesn"t have a preference on the return type, so let"s start
          //small and go from there...
          if (expPos > -1 && expPos < val.length() - 1) {
              exp = val.substring(expPos + 1, val.length());
          } else {
              exp = null;
          }
          if (dec == null && exp == null) {
              //Must be an int,long,bigint
              try {
                  return createInteger(val);
              } catch (NumberFormatException nfe) {
                  // empty catch
              }
              try {
                  return createLong(val);
              } catch (NumberFormatException nfe) {
                  // empty catch
              }
              return createBigInteger(val);
          } else {
              //Must be a float,double,BigDec
              boolean allZeros = isAllZeros(mant) && isAllZeros(exp);
              try {
                  Float f = createFloat(val);
                  if (!(f.isInfinite() || (f.floatValue() == 0.0F && !allZeros))) {
                      return f;
                  }
              } catch (NumberFormatException nfe) {
                  // empty catch
              }
              try {
                  Double d = createDouble(val);
                  if (!(d.isInfinite() || (d.doubleValue() == 0.0D && !allZeros))) {
                      return d;
                  }
              } catch (NumberFormatException nfe) {
                  // empty catch
              }
              return createBigDecimal(val);
          }
      }
  }
  /**
   * <p>Utility method for {@link #createNumber(java.lang.String)}.</p>
   *
   * <p>Returns <code>true</code> if s is <code>null</code>.</p>
   * 
   * @param s the String to check
   * @return if it is all zeros or <code>null</code>
   */
  private static boolean isAllZeros(String s) {
      if (s == null) {
          return true;
      }
      for (int i = s.length() - 1; i >= 0; i--) {
          if (s.charAt(i) != "0") {
              return false;
          }
      }
      return s.length() > 0;
  }
  //--------------------------------------------------------------------
  
  /**
   * <p>Convert a <code>String</code> to a <code>Float</code>.</p>
   * 
   * @param val  a <code>String</code> to convert
   * @return converted <code>Float</code>
   * @throws NumberFormatException if the value cannot be converted
   */
  public static Float createFloat(String val) {
      return Float.valueOf(val);
  }
  /**
   * <p>Convert a <code>String</code> to a <code>Double</code>.</p>
   * 
   * @param val  a <code>String</code> to convert
   * @return converted <code>Double</code>
   * @throws NumberFormatException if the value cannot be converted
   */
  public static Double createDouble(String val) {
      return Double.valueOf(val);
  }
  /**
   * <p>Convert a <code>String</code> to a <code>Integer</code>, handling
   * hex and octal notations.</p>
   * 
   * @param val  a <code>String</code> to convert
   * @return converted <code>Integer</code>
   * @throws NumberFormatException if the value cannot be converted
   */
  public static Integer createInteger(String val) {
      // decode() handles 0xAABD and 0777 (hex and octal) as well.
      return Integer.decode(val);
  }
  /**
   * <p>Convert a <code>String</code> to a <code>Long</code>.</p>
   * 
   * @param val  a <code>String</code> to convert
   * @return converted <code>Long</code>
   * @throws NumberFormatException if the value cannot be converted
   */
  public static Long createLong(String val) {
      return Long.valueOf(val);
  }
  /**
   * <p>Convert a <code>String</code> to a <code>BigInteger</code>.</p>
   * 
   * @param val  a <code>String</code> to convert
   * @return converted <code>BigInteger</code>
   * @throws NumberFormatException if the value cannot be converted
   */
  public static BigInteger createBigInteger(String val) {
      BigInteger bi = new BigInteger(val);
      return bi;
  }
  /**
   * <p>Convert a <code>String</code> to a <code>BigDecimal</code>.</p>
   * 
   * @param val  a <code>String</code> to convert
   * @return converted <code>BigDecimal</code>
   * @throws NumberFormatException if the value cannot be converted
   */
  public static BigDecimal createBigDecimal(String val) {
      BigDecimal bd = new BigDecimal(val);
      return bd;
  }
  
  //--------------------------------------------------------------------
  
  /**
   * <p>Checks whether the <code>String</code> contains only
   * digit characters.</p>
   *
   * <p><code>Null</code> and empty String will return
   * <code>false</code>.</p>
   *
   * @param str  the <code>String</code> to check
   * @return <code>true</code> if str contains only unicode numeric
   */
  public static boolean isDigits(String str) {
      if ((str == null) || (str.length() == 0)) {
          return false;
      }
      for (int i = 0; i < str.length(); i++) {
          if (!Character.isDigit(str.charAt(i))) {
              return false;
          }
      }
      return true;
  }
}





Various number-related routines and classes that are frequently used

  
/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * 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.
 */

import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Various number-related routines and classes that are frequently used.
 * 
 * @author barclay
 */
public class Number {
  /**
   * Default number of decimal places to round to:
   */
  public static final int DECIMAL_PLACES = 2;
  /**
   * Round a float to the default number of decimal places.
   * 
   * @param value
   *          The value to round.
   * @return The rounded value as a float.
   * @see #DECIMAL_PLACES
   */
  public static float Round(float value) {
    return Round(value, DECIMAL_PLACES);
  }
  /**
   * Round a float to the specified number of decimal places.
   * 
   * @param value
   *          The value to round.
   * @param places
   *          The number of decimal points.
   * @return The rounded value as a float.
   */
  public static float Round(float value, int places) {
    float p = (float) Math.pow(10, places);
    value = value * p;
    float tmp = Math.round(value);
    return (float) tmp / p;
  }
  /**
   * Clamp a <code>value</code> to <code>min</code> or <code>max</code>,
   * inclusive.
   * 
   * @param value
   *          The value to clamp.
   * @param min
   *          The minimum value.
   * @param max
   *          The maximum value.
   * @return If <code>value</code> is greater than <code>max</code> then
   *         <code>max</code>, else if <code>value</code> is less than
   *         <code>min</code> then <code>min</code>, else <code>value</code>.
   */
  public static float Clamp(float value, float min, float max) {
    if (value > max)
      return max;
    if (value < min)
      return min;
    return value;
  }
  public enum TrendState {
    DOWN_15_GOOD,
    DOWN_15_BAD,
    DOWN_30_GOOD,
    DOWN_30_BAD,
    DOWN_45_GOOD,
    DOWN_45_BAD,
    UP_15_GOOD,
    UP_15_BAD,
    UP_30_GOOD,
    UP_30_BAD,
    UP_45_GOOD,
    UP_45_BAD,
    DOWN_15,
    UP_15,
    FLAT,
    FLAT_GOAL,
    UNKNOWN
  };
  public static TrendState getTrendState(float oldTrend, float newTrend,
      float goal, float sensitivity, float stdDev) {
    sensitivity = sensitivity * stdDev;
    float half = sensitivity / 2.0f;
    float quarter = sensitivity / 4.0f;
    if (oldTrend == newTrend) {
      // truly flat trend
      if (newTrend == goal)
        // perfect!
        return TrendState.FLAT_GOAL;
      else if (newTrend < goal && newTrend + quarter > goal)
        // flat near the goal!
        return TrendState.FLAT_GOAL;
      else if (newTrend > goal && newTrend - quarter < goal)
        // flat near the goal!
        return TrendState.FLAT_GOAL;
      else
        return TrendState.FLAT;
    } else if (oldTrend > newTrend) {
      // going down
      if (oldTrend > goal && newTrend > goal) {
        // toward goal
        if (oldTrend - newTrend > sensitivity)
          // huge drop
          return TrendState.DOWN_45_GOOD;
        else if (oldTrend - newTrend > half)
          // big drop
          return TrendState.DOWN_30_GOOD;
        else if (oldTrend - newTrend > quarter)
          // little drop
          return TrendState.DOWN_15_GOOD;
        else {
          // under bounds for flat
          if (newTrend - quarter < goal)
            // flat near the goal!
            return TrendState.FLAT_GOAL;
          else
            // flat elsewhere
            return TrendState.FLAT;
        }
      } else if (oldTrend < goal && newTrend < goal) {
        // away from goal
        if (oldTrend - newTrend > sensitivity)
          // huge drop
          return TrendState.DOWN_45_BAD;
        else if (oldTrend - newTrend > half)
          // big drop
          return TrendState.DOWN_30_BAD;
        else if (oldTrend - newTrend > quarter)
          // little drop
          return TrendState.DOWN_15_BAD;
        else {
          // under bounds for flat
          if (newTrend + quarter > goal)
            // flat near the goal!
            return TrendState.FLAT_GOAL;
          else
            // flat elsewhere
            return TrendState.FLAT;
        }
      } else
        // crossing goal line
        return TrendState.DOWN_15;
    } else if (oldTrend < newTrend) {
      // going up
      if (oldTrend < goal && newTrend < goal) {
        // toward goal
        if (newTrend - oldTrend > sensitivity)
          // big rise
          return TrendState.UP_45_GOOD;
        else if (newTrend - oldTrend > half)
          // little rise
          return TrendState.UP_30_GOOD;
        else if (newTrend - oldTrend > quarter)
          // little rise
          return TrendState.UP_15_GOOD;
        else {
          // under bounds for flat
          if (newTrend + quarter > goal)
            // flat near the goal!
            return TrendState.FLAT_GOAL;
          else
            // flat elsewhere
            return TrendState.FLAT;
        }
      } else if (oldTrend > goal && newTrend > goal) {
        // away from goal
        if (newTrend - oldTrend > sensitivity)
          // big rise
          return TrendState.UP_45_BAD;
        else if (newTrend - oldTrend > half)
          // little rise
          return TrendState.UP_30_BAD;
        else if (newTrend - oldTrend > quarter)
          // little rise
          return TrendState.UP_15_BAD;
        else {
          // under bounds for flat
          if (newTrend - quarter < goal)
            // flat near the goal!
            return TrendState.FLAT_GOAL;
          else
            // flat elsewhere
            return TrendState.FLAT;
        }
      } else {
        // crossing goal line
        return TrendState.UP_15;
      }
    } else
      // ??
      return TrendState.UNKNOWN;
  }
  /**
   * An exponentially smoothed weighted moving average. Not thread safe. Trend
   * is calculated thusly: <br>
   * <code>
   * trend[n] := trend[n-1] + smoothing_percentage * (value[n] - value[n-1])
   * </code>
   * 
   * @author barclay
   */
  public static class Trend {
    /**
     * Default smoothing percentage. This value will be used to scale the
     * previous entry by multiplying the previous entry"s value and adding that
     * to the current value, so a smoothing percentage of 0.1 is 10%.
     */
    private static final float DEFAULT_SMOOTHING = 0.1f;
    private int mNEntries = 0;
    private float mSmoothing = DEFAULT_SMOOTHING;
    private float mSum = 0.0f;
    private boolean mFirst = true;
    private float mTrendLast = 0.0f;
    public float mTrendPrev = 0.0f;
    public float mTrend = 0.0f;
    public float mMin = 0.0f;
    public float mMax = 0.0f;
    public float mMean = 0.0f;
    /**
     * Default constructor. Set the smoothing percentage to the default.
     * 
     * @see #DEFAULT_SMOOTHING
     */
    public Trend() {
    }
    /**
     * Constructor
     * 
     * @param smoothing
     *          Sets the smoothing percentage to the specified value.
     * @see #DEFAULT_SMOOTHING
     */
    public Trend(float smoothing) {
      mSmoothing = smoothing;
    }
    /**
     * Copy Constructor
     * 
     * @param source
     *          Returns a new instance of Trend with all data set to source.
     * @see #DEFAULT_SMOOTHING
     */
    public Trend(Trend source) {
      mNEntries = source.mNEntries;
      mSmoothing = source.mSmoothing;
      mSum = source.mSum;
      mFirst = source.mFirst;
      mTrendLast = source.mTrendLast;
      mTrendPrev = source.mTrendPrev;
      mTrend = source.mTrend;
      mMin = source.mMin;
      mMax = source.mMax;
      mMean = source.mMean;
    }
    /**
     * Return the smoothing constant used by the Trend.
     * 
     * @return The smoothing constant as a float.
     */
    public float getSmoothing() {
      return mSmoothing;
    }
    /**
     * Update the trend with a new value. The value is implicitly "later" in the
     * sequence than all previous values.
     * 
     * @param val
     *          The value to add to the series.
     */
    public void update(float val) {
      mNEntries++;
      mSum += val;
      float oldMean = mMean;
      mMean += (val - oldMean) / mNEntries;
      // T(n) = T(n-1) + 0.1(V(n) - T(n-1))
      // : T(n) is the trend number for day n
      // : V(n) is the value number for day n
      // : S is the smoothing factor (default 0.1)
      if (mFirst == true) {
        mFirst = false;
        mTrend = val;
        mMin = val;
        mMax = val;
      } else {
        mTrend = mTrendLast + (mSmoothing * (val - mTrendLast));
        if (mTrend < mMin)
          mMin = mTrend;
        if (mTrend > mMax)
          mMax = mTrend;
      }
      mTrendPrev = mTrendLast;
      mTrendLast = mTrend;
    }
  }
  /**
   * Class for keeping track of various statistics intended to be updated
   * incrementally, including total number of updates, sum, mean, variance, and
   * standard deviation of the series. Not thread safe.
   * 
   * @author barclay
   */
  public static class RunningStats {
    public int mNDatapoints = 0;
    public int mNEntries = 0;
    public float mSum = 0.0f;
    public float mMean = 0.0f;
    public float mEntryMean = 0.0f;
    public float mVarSum = 0.0f;
    public float mVar = 0.0f;
    public float mStdDev = 0.0f;
    /**
     * Sole constructor. Initializes all stats to 0.
     */
    public RunningStats() {
    }
    /**
     * Copy Constructor
     * 
     * @param source
     *          Returns a new instance of RunningStats with all data set to
     *          source.
     */
    public RunningStats(RunningStats source) {
      mNDatapoints = source.mNDatapoints;
      mNEntries = source.mNEntries;
      mSum = source.mSum;
      mMean = source.mMean;
      mEntryMean = source.mEntryMean;
      mVarSum = source.mVarSum;
      mVar = source.mVar;
      mStdDev = source.mStdDev;
    }
    /**
     * update the statistics with the specified value. The value may be an
     * aggregate of several other values, as indicated by the second parameter.
     * A separate value will be recored for per-entry and and per-update means.
     * 
     * @param val
     *          The value to update the statistics with.
     * @param nEntries
     *          The number of entries this value is an aggregate of.
     */
    public void update(float val, int nEntries) {
      mNDatapoints++;
      mNEntries += nEntries;
      mSum += val;
      // Mean is calculated thusly to avoid float expansion and contraction,
      // which
      // would minimize accuracy.
      float oldMean = mMean;
      mMean += (val - oldMean) / mNDatapoints;
      mVarSum += (val - oldMean) * (val - mMean);
      mVar = mVarSum / mNDatapoints;
      mStdDev = (float) Math.sqrt(mVar);
      if (mNEntries > 0) {
        float oldEntryMean = mEntryMean;
        mEntryMean += (val - oldEntryMean) / mNEntries;
      }
      return;
    }
  }
  /**
   * Class for keeping track of the Standard Deviation over the last X values.
   * 
   * @author barclay
   */
  public static class WindowedStdDev {
    private Lock mLock;
    private ArrayList<Float> mValues;
    private int mHistory;
    /**
     * Sole constructor. Initializes all stats to 0.
     */
    public WindowedStdDev(int history) {
      mHistory = history;
      mValues = new ArrayList<Float>(mHistory);
      mLock = new ReentrantLock();
    }
    /**
     * Copy Constructor
     * 
     * @param source
     *          Returns a new instance of WindowedStdDev with all data set to
     *          source.
     */
    public WindowedStdDev(WindowedStdDev source) {
      mLock = new ReentrantLock();
      source.waitForLock();
      mHistory = source.mHistory;
      mValues = new ArrayList<Float>(mHistory);
      for (int i = 0; i < source.mValues.size(); i++) {
        try {
          mValues.add(new Float(source.mValues.get(i)));          
        } catch(IndexOutOfBoundsException e) {
          break;
        }
      }
      source.unlock();
    }
    public void waitForLock() {
      while (lock() == false) {
      }
    }
    public boolean lock() {
      try {
        return mLock.tryLock(250L, TimeUnit.MILLISECONDS);
      } catch (InterruptedException e) {
        return false;
      }
    }
    public void unlock() {
      mLock.unlock();
    }
    /**
     * update the std dev with the specified value.
     * 
     * @param val
     *          The value to update the statistics with.
     */
    public void update(float val) {
      waitForLock();
      mValues.add(new Float(val));
      if (mValues.size() > mHistory) {
        try {
          mValues.remove(0);
        } catch(IndexOutOfBoundsException e) {
          // nothing
        }
      }
      unlock();
      return;
    }
    /**
     * Fetch current Standard Deviation.
     * 
     * @param val
     *          The value to update the statistics with.
     */
    public float getStandardDev() {
      float mean = 0.0f;
      float meanSqr = 0.0f;
      float variance = 0.0f;
      float delta = 0.0f;
      float val = 0.0f;
      waitForLock();
      int nValues = mValues.size();
      for (int i = 0; i < nValues; i++) {
        try {
          val = mValues.get(i);
          delta = val - mean;
          mean = mean + delta / (i + 1);
          meanSqr = meanSqr + delta * (val - mean);
        } catch(IndexOutOfBoundsException e) {
          break;
        }
      }
      unlock();
      
      variance = meanSqr / nValues;
      return (float) Math.sqrt(variance);
    }
  }
  /**
   * Performs a standard Pearson linear correlation on multiple series of data
   * at one, returning the results in a matrix.
   * 
   * @author barclay
   */
  public static class LinearMatrixCorrelation {
    private int mNumSeries = 0;
    private int mNEntries = 0;
    private Float[] mSum;
    private Float[] mMean;
    private Float[] mSumSquare;
    private Float[] mStdDev;
    private Float[][] mSumCoproduct;
    private Float[][] mCovariance;
    private Float[][] mCorrelation;
    /**
     * Constructor. Allocates internal data structures and zero"s out the output
     * matrix data.
     * 
     * @param numSeries
     *          The number of series that will be included in each call to
     *          <code>update()</code>.
     */
    public LinearMatrixCorrelation(int numSeries) {
      mNumSeries = numSeries;
      mSum = new Float[numSeries];
      mMean = new Float[numSeries];
      mSumSquare = new Float[numSeries];
      mStdDev = new Float[numSeries];
      mSumCoproduct = new Float[numSeries][];
      mCovariance = new Float[numSeries][];
      mCorrelation = new Float[numSeries][];
      for (int i = 0; i < numSeries; i++) {
        mSum[i] = 0.0f;
        mMean[i] = 0.0f;
        mSumSquare[i] = 0.0f;
        mStdDev[i] = 0.0f;
        mSumCoproduct[i] = new Float[numSeries];
        mCovariance[i] = new Float[numSeries];
        mCorrelation[i] = new Float[numSeries];
        for (int j = 0; j < numSeries; j++) {
          mSumCoproduct[i][j] = 0.0f;
          mCovariance[i][j] = 0.0f;
          mCorrelation[i][j] = 0.0f;
        }
      }
    }
    /**
     * Adds a vector (array) of values, 1 per series, to the calculations.
     * Graphically, all values are considered to be the at the same X (or Y)
     * position, and the values in the array argument denote the corresponding Y
     * (or X) value specific to the each series. Thus, the parameter x is an
     * array of values x[0 .. numSeries-1], one value per series, all of which
     * occured at the same "time." If a series has no such value, the entry in
     * the array should be null, as the length of the array must match the
     * <code>numSeries</code> past into the constructor at each invocation.
     * 
     * @param x
     *          The values for each series as Floats.
     * @return true if the input acceptable, else false if the length of
     *         <code>x[]</code> does not match <code>numSeries</code> or a value
     *         less than 1 was passed to the constructor.
     * @see LinearMatrixCorrelation#LinearMatrixCorrelation
     */
    public boolean update(Float[] x) {
      float oldMean;
      if (x.length != mNumSeries)
        return false;
      if (mNEntries + 1 > mNumSeries)
        return false;
      mNEntries++;
      float sweep = (mNEntries - 1.0f) / mNEntries;
      for (int i = 0; i < x.length; i++) {
        if (x[i] != null) {
          mSum[i] += x[i];
          oldMean = mMean[i];
          mMean[i] += (x[i] - oldMean) / mNEntries;
          mSumSquare[i] += (x[i] - oldMean) * (x[i] - mMean[i]);
          mStdDev[i] = (float) Math.sqrt(mSumSquare[i] * sweep);
        }
      }
      for (int i = 0; i < x.length; i++) {
        if (x[i] != null) {
          for (int j = i + 1; j < x.length; j++) {
            if (x[j] != null) {
              mSumCoproduct[i][j] += (x[i] - mMean[i]) * (x[j] - mMean[j]);
              mCovariance[i][j] = mSumCoproduct[i][j] * sweep;
              mCorrelation[i][j] = mCovariance[i][j]
                  / (mStdDev[i] * mStdDev[j]);
              mCorrelation[j][i] = mCovariance[i][j]
                  / (mStdDev[i] * mStdDev[j]);
              mCorrelation[i][j] = mCovariance[i][j]
                  / (mStdDev[i] * mStdDev[j]);
            }
          }
        }
        mCorrelation[i][i] = 1.0f;
      }
      return true;
    }
    /**
     * Returns a reference to the correlation output matrix. The upper right
     * triangle is a mirror of the lower left, and the dividing diagonal the
     * identity correlation, i.e., 1.0f. In order to run through the matrix
     * without duplicates (e.g., processing both output[i][j] and output[j][i],
     * use a construct like: <br>
     * 
     * <pre>
     * for (int i = 0; i &lt; output.length; i++) {
     *   for (int j = i+1; j &lt; output.length; j++) {
     *     if (output[i][j] != null) { ... }
     *   }
     * }
     * </pre>
     * 
     * Note that any correlations that could not be calculated, either due to
     * lack of datapoints or structure of the data, will be null.
     * 
     * @return Float[][], the output correlation matrix.
     */
    public Float[][] getCorrelations() {
      return mCorrelation;
    }
    /**
     * Return a string interpretation of the linear correlation value. Note that
     * this is highly dependent on the data being correlated, and should be no
     * means be taken as gospel.
     * 
     * @param c
     *          The correlation value, should be -1.0f <= c <= 1.0f.
     * @return A string interpretation.
     */
    public static String correlationToString(float c) {
      if (c > 0.5)
        return "Strong";
      if (c < -0.5)
        return "Inverse Strong";
      if (c > 0.3)
        return "Medium";
      if (c < -0.3)
        return "Inverse Medium";
      return "Weak";
    }
  }
}