| package org.apache.velocity.tools.generic; |
| |
| /* |
| * 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.io.Serializable; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Iterator; |
| import org.apache.commons.beanutils.PropertyUtils; |
| import org.apache.velocity.tools.ConversionUtils; |
| import org.apache.velocity.tools.Scope; |
| import org.apache.velocity.tools.config.DefaultKey; |
| import org.apache.velocity.tools.config.ValidScope; |
| |
| /** |
| * <p>Tool for performing math in Velocity.</p> |
| * |
| * <p>Some things should be noted here:</p> |
| * <ul> |
| * <li>This class does not have methods that take |
| * primitives. This is simply because Velocity |
| * wraps all primitives for us automagically.</li> |
| * |
| * <li>No null pointer, number format, or divide by zero |
| * exceptions are thrown here. This is because such exceptions |
| * thrown in template halt rendering. It should be sufficient |
| * debugging feedback that Velocity will render the reference |
| * literally. (e.g. $math.div(1, 0) renders as '$math.div(1, 0)')</li> |
| * </ul> |
| * <p>Example tools.xml config:</p> |
| * <pre> |
| * <tools> |
| * <toolbox scope="application"> |
| * <tool class="org.apache.velocity.tools.generic.MathTool"/> |
| * </toolbox> |
| * </tools> |
| * </pre> |
| * |
| * @author Nathan Bubna |
| * @author Leon Messerschmidt |
| * @version $Revision$ $Date$ |
| */ |
| |
| @DefaultKey("math") |
| @ValidScope(Scope.APPLICATION) |
| public class MathTool extends FormatConfig implements Serializable |
| { |
| private static final long serialVersionUID = 3207828679772113341L; |
| |
| public Number add(Object num1, Object num2) |
| { |
| return add(new Object[] { num1, num2 }); |
| } |
| |
| public Number sub(Object num1, Object num2) |
| { |
| return sub(new Object[] { num1, num2 }); |
| } |
| |
| public Number mul(Object num1, Object num2) |
| { |
| return mul(new Object[] { num1, num2 }); |
| } |
| |
| public Number div(Object num1, Object num2) |
| { |
| return div(new Object[] { num1, num2 }); |
| } |
| |
| public Number max(Object num1, Object num2) |
| { |
| return max(new Object[] { num1, num2 }); |
| } |
| |
| public Number min(Object num1, Object num2) |
| { |
| return min(new Object[] { num1, num2 }); |
| } |
| |
| public Number bitwiseOr(Object num1, Object num2) |
| { |
| return bitwiseOr(new Object[] { num1, num2 }); |
| } |
| |
| public Number bitwiseAnd(Object num1, Object num2) |
| { |
| return bitwiseAnd(new Object[] { num1, num2 }); |
| } |
| |
| public Number bitwiseXOr(Object num1, Object num2) |
| { |
| return bitwiseXOr(new Object[] { num1, num2 }); |
| } |
| |
| /** |
| * @param nums the numbers to be added |
| * @return the sum of the numbers or |
| * <code>null</code> if they're invalid |
| * @see #toNumber |
| */ |
| public Number add(Object... nums) |
| { |
| double value = 0; |
| Number[] ns = new Number[nums.length]; |
| for (int i=0; i<nums.length; i++) |
| { |
| Number n = toNumber(nums[i]); |
| if (n == null) |
| { |
| return null; |
| } |
| value += n.doubleValue(); |
| ns[i] = n; |
| } |
| return matchType(value, ns); |
| } |
| |
| |
| /** |
| * @param nums the numbers to be subtracted |
| * @return the difference of the numbers (subtracted in order) or |
| * <code>null</code> if they're invalid |
| * @see #toNumber |
| */ |
| public Number sub(Object... nums) |
| { |
| double value = 0; |
| Number[] ns = new Number[nums.length]; |
| for (int i=0; i<nums.length; i++) |
| { |
| Number n = toNumber(nums[i]); |
| if (n == null) |
| { |
| return null; |
| } |
| if (i == 0) |
| { |
| value = n.doubleValue(); |
| } |
| else |
| { |
| value -= n.doubleValue(); |
| } |
| ns[i] = n; |
| } |
| return matchType(value, ns); |
| } |
| |
| |
| /** |
| * @param nums the numbers to be multiplied |
| * @return the product of the numbers or |
| * <code>null</code> if they're invalid |
| * @see #toNumber |
| */ |
| public Number mul(Object... nums) |
| { |
| double value = 1; |
| Number[] ns = new Number[nums.length]; |
| for (int i=0; i<nums.length; i++) |
| { |
| Number n = toNumber(nums[i]); |
| if (n == null) |
| { |
| return null; |
| } |
| value *= n.doubleValue(); |
| ns[i] = n; |
| } |
| return matchType(value, ns); |
| } |
| |
| |
| /** |
| * @param nums the numbers to be divided |
| * @return the quotient of the numbers or |
| * <code>null</code> if they're invalid |
| * or if any denominator equals zero |
| * @see #toNumber |
| */ |
| public Number div(Object... nums) |
| { |
| double value = 0; |
| Number[] ns = new Number[nums.length]; |
| for (int i=0; i<nums.length; i++) |
| { |
| Number n = toNumber(nums[i]); |
| if (n == null) |
| { |
| return null; |
| } |
| if (i == 0) |
| { |
| value = n.doubleValue(); |
| } |
| else |
| { |
| double denominator = n.doubleValue(); |
| if (denominator == 0.0) |
| { |
| return null; |
| } |
| value /= denominator; |
| } |
| ns[i] = n; |
| } |
| return matchType(value, ns); |
| } |
| |
| |
| /** |
| * @param num1 the first number |
| * @param num2 the second number |
| * @return the first number raised to the power of the |
| * second or <code>null</code> if they're invalid |
| * @see #toNumber |
| */ |
| public Number pow(Object num1, Object num2) |
| { |
| Number n1 = toNumber(num1); |
| Number n2 = toNumber(num2); |
| if (n1 == null || n2 == null) |
| { |
| return null; |
| } |
| double value = Math.pow(n1.doubleValue(), n2.doubleValue()); |
| return matchType(n1, n2, value); |
| } |
| |
| |
| /** |
| * Does integer division on the int values of the specified numbers. |
| * |
| * <p>So, $math.idiv('5.1',3) will return '1', |
| * and $math.idiv(6,'3.9') will return '2'.</p> |
| * |
| * @param num1 the first number |
| * @param num2 the second number |
| * @return the result of performing integer division |
| * on the operands. |
| * @see #toInteger |
| */ |
| public Integer idiv(Object num1, Object num2) |
| { |
| Number n1 = toNumber(num1); |
| Number n2 = toNumber(num2); |
| if (n1 == null || n2 == null || n2.intValue() == 0) |
| { |
| return null; |
| } |
| int value = n1.intValue() / n2.intValue(); |
| return Integer.valueOf(value); |
| } |
| |
| |
| /** |
| * Does integer modulus on the int values of the specified numbers. |
| * |
| * <p>So, $math.mod('5.1',3) will return '2', |
| * and $math.mod(6,'3.9') will return '0'.</p> |
| * |
| * @param num1 the first number |
| * @param num2 the second number |
| * @return the result of performing integer modulus |
| * on the operands. |
| * @see #toInteger |
| */ |
| public Integer mod(Object num1, Object num2) |
| { |
| Number n1 = toNumber(num1); |
| Number n2 = toNumber(num2); |
| if (n1 == null || n2 == null || n2.intValue() == 0) |
| { |
| return null; |
| } |
| int value = n1.intValue() % n2.intValue(); |
| return Integer.valueOf(value); |
| } |
| |
| |
| /** |
| * Bitwise Or |
| * @param nums the numbers to be Or'ed |
| * @return the bitwise Or of the numbers or |
| * <code>null</code> if they're invalid |
| * @see #toInteger |
| */ |
| public Number bitwiseOr(Object... nums) |
| { |
| long value = 0; |
| Number[] ns = new Number[nums.length]; |
| for (int i=0; i<nums.length; i++) |
| { |
| Long n = toLong(nums[i]); |
| if (n == null) |
| { |
| return null; |
| } |
| value |= n.longValue(); |
| ns[i] = n; |
| } |
| return matchType(value, ns); |
| } |
| |
| /** |
| * Bitwise And |
| * @param nums the numbers to be And'ed |
| * @return the bitwise And of the numbers or |
| * <code>null</code> if they're invalid |
| * @see #toInteger |
| */ |
| public Number bitwiseAnd(Object... nums) |
| { |
| long value = -1; |
| Number[] ns = new Number[nums.length]; |
| for (int i=0; i<nums.length; i++) |
| { |
| Long n = toLong(nums[i]); |
| if (n == null) |
| { |
| return null; |
| } |
| value &= n.longValue(); |
| ns[i] = n; |
| } |
| return matchType(value, ns); |
| } |
| |
| /** |
| * Bitwise XOr |
| * @param nums the numbers to be XOr'ed |
| * @return the bitwise XOr of the numbers or |
| * <code>null</code> if they're invalid |
| * @see #toInteger |
| */ |
| public Number bitwiseXOr(Object... nums) |
| { |
| long value = 0; |
| Number[] ns = new Number[nums.length]; |
| for (int i=0; i<nums.length; i++) |
| { |
| Long n = toLong(nums[i]); |
| if (n == null) |
| { |
| return null; |
| } |
| value ^= n.longValue(); |
| ns[i] = n; |
| } |
| return matchType(value, ns); |
| } |
| |
| |
| /** |
| * @param nums the numbers to be searched |
| * @return the largest of the numbers or |
| * <code>null</code> if they're invalid |
| * @see #toNumber |
| */ |
| public Number max(Object... nums) |
| { |
| double value = Double.MIN_VALUE; |
| Number[] ns = new Number[nums.length]; |
| for (int i=0; i<nums.length; i++) |
| { |
| Number n = toNumber(nums[i]); |
| if (n == null) |
| { |
| return null; |
| } |
| value = Math.max(value, n.doubleValue()); |
| ns[i] = n; |
| } |
| return matchType(value, ns); |
| } |
| |
| |
| /** |
| * @param nums the numbers to be searched |
| * @return the smallest of the numbers or |
| * <code>null</code> if they're invalid |
| * @see #toNumber |
| */ |
| public Number min(Object... nums) |
| { |
| double value = Double.MAX_VALUE; |
| Number[] ns = new Number[nums.length]; |
| for (int i=0; i<nums.length; i++) |
| { |
| Number n = toNumber(nums[i]); |
| if (n == null) |
| { |
| return null; |
| } |
| value = Math.min(value, n.doubleValue()); |
| ns[i] = n; |
| } |
| return matchType(value, ns); |
| } |
| |
| |
| /** |
| * @param num the number |
| * @return the absolute value of the number or |
| * <code>null</code> if it's invalid |
| * @see #toDouble |
| */ |
| public Number abs(Object num) |
| { |
| Number n = toNumber(num); |
| if (n == null) |
| { |
| return null; |
| } |
| double value = Math.abs(n.doubleValue()); |
| return matchType(n, value); |
| } |
| |
| |
| /** |
| * @param num the number |
| * @return the smallest integer that is not |
| * less than the given number |
| */ |
| public Integer ceil(Object num) |
| { |
| Number n = toNumber(num); |
| if (n == null) |
| { |
| return null; |
| } |
| return Integer.valueOf((int)Math.ceil(n.doubleValue())); |
| } |
| |
| |
| /** |
| * @param num the number |
| * @return the integer portion of the number |
| */ |
| public Integer floor(Object num) |
| { |
| Number n = toNumber(num); |
| if (n == null) |
| { |
| return null; |
| } |
| return Integer.valueOf((int)Math.floor(n.doubleValue())); |
| } |
| |
| |
| /** |
| * Rounds a number to the nearest whole Integer |
| * |
| * @param num the number to round |
| * @return the number rounded to the nearest whole Integer |
| * or <code>null</code> if it's invalid |
| * @see java.lang.Math#rint(double) |
| */ |
| public Integer round(Object num) |
| { |
| Number n = toNumber(num); |
| if (n == null) |
| { |
| return null; |
| } |
| return Integer.valueOf((int)Math.rint(n.doubleValue())); |
| } |
| |
| |
| /** |
| * Rounds a number to the specified number of decimal places. |
| * This is particulary useful for simple display formatting. |
| * If you want to round an number to the nearest integer, it |
| * is better to use {@link #round}, as that will return |
| * an {@link Integer} rather than a {@link Double}. |
| * |
| * @param decimals the number of decimal places |
| * @param num the number to round |
| * @return the value rounded to the specified number of |
| * decimal places or <code>null</code> if it's invalid |
| * @see #toNumber |
| */ |
| public Double roundTo(Object decimals, Object num) |
| { |
| Number i = toNumber(decimals); |
| Number d = toNumber(num); |
| if (i == null || d == null) |
| { |
| return null; |
| } |
| //ok, go ahead and do the rounding |
| int places = i.intValue(); |
| double value = d.doubleValue(); |
| int delta = 10; |
| for(int j=1;j<places;j++) { |
| delta *= 10; |
| } |
| return new Double((double)Math.round(value*delta)/delta); |
| } |
| |
| |
| /** |
| * @return a pseudo-random {@link Double} greater |
| * than or equal to 0.0 and less than 1.0 |
| * @see Math#random() |
| */ |
| public Double getRandom() |
| { |
| return new Double(Math.random()); |
| } |
| |
| |
| /** |
| * This returns a random {@link Number} within the |
| * specified range. The returned value will be |
| * greater than or equal to the first number |
| * and less than the second number. If both arguments |
| * are whole numbers then the returned number will |
| * also be, otherwise a {@link Double} will |
| * be returned. |
| * |
| * @param num1 the first number |
| * @param num2 the second number |
| * @return a pseudo-random {@link Number} greater than |
| * or equal to the first number and less than |
| * the second |
| * @see Math#random() |
| */ |
| public Number random(Object num1, Object num2) |
| { |
| Number n1 = toNumber(num1); |
| Number n2 = toNumber(num2); |
| if (n1 == null || n2 == null) |
| { |
| return null; |
| } |
| |
| double diff = n2.doubleValue() - n1.doubleValue(); |
| // multiply the difference by a pseudo-random double from |
| // 0.0 to 1.0, round to the nearest int, and add the first |
| // value to the random int and return as an Integer |
| double random = (diff * Math.random()) + n1.doubleValue(); |
| |
| // check if either of the args were floating points |
| String in = n1.toString() + n2.toString(); |
| if (in.indexOf('.') < 0) |
| { |
| // args were whole numbers, so return the same |
| return matchType(n1, n2, Math.floor(random)); |
| } |
| // one of the args was a floating point, |
| // so don't floor the result |
| return new Double(random); |
| } |
| |
| |
| // --------------- public type conversion methods --------- |
| |
| /** |
| * Converts an object with a numeric value into an Integer |
| * Valid formats are {@link Number} or a {@link String} |
| * representation of a number |
| * |
| * @param num the number to be converted |
| * @return a {@link Integer} representation of the number |
| * or <code>null</code> if it's invalid |
| * @deprecated use {@link NumberTool#toNumber(Object)}.intValue() |
| */ |
| @Deprecated |
| public Integer toInteger(Object num) |
| { |
| Number n = toNumber(num); |
| if (n == null) |
| { |
| return null; |
| } |
| return Integer.valueOf(n.intValue()); |
| } |
| |
| /** |
| * Converts an object with a numeric value into a Long integer |
| * Valid formats are {@link Number} or a {@link String} |
| * representation of a number |
| * |
| * @param num the number to be converted |
| * @return a {@link Long} integer representation of the number |
| * or <code>null</code> if it's invalid |
| * @deprecated use {@link NumberTool#toNumber(Object)}.longValue() |
| */ |
| @Deprecated |
| public Long toLong(Object num) |
| { |
| Number n = toNumber(num); |
| if (n == null) |
| { |
| return null; |
| } |
| return Long.valueOf(n.longValue()); |
| } |
| |
| /** |
| * Converts an object with a numeric value into a Double |
| * Valid formats are {@link Number} or a {@link String} |
| * representation of a number |
| * |
| * @param num the number to be converted |
| * @return a {@link Double} representation of the number |
| * or <code>null</code> if it's invalid |
| * @deprecated use {@link NumberTool#toNumber(Object)}.doubleValue() |
| */ |
| @Deprecated |
| public Double toDouble(Object num) |
| { |
| Number n = toNumber(num); |
| if (n == null) |
| { |
| return null; |
| } |
| return new Double(n.doubleValue()); |
| } |
| |
| |
| /** |
| * Converts an object with a numeric value into a Number |
| * Valid formats are {@link Number} or a {@link String} |
| * representation of a number. Note that this does not |
| * handle localized number formats. Use the {@link NumberTool} |
| * to handle such conversions. |
| * |
| * @param num the number to be converted |
| * @return a {@link Number} representation of the number |
| * or <code>null</code> if it's invalid |
| * @deprecated use {@link NumberTool#toNumber(Object)} |
| */ |
| @Deprecated |
| public Number toNumber(Object num) |
| { |
| return ConversionUtils.toNumber(num, getFormat(), getLocale()); |
| } |
| |
| |
| // --------------------------- protected methods ------------------ |
| |
| /** |
| * @param in instance of wanted Number class |
| * @param out input number |
| * @return wanted Number |
| * @see #matchType(double,Number...) |
| */ |
| protected Number matchType(Number in, double out) |
| { |
| return matchType(out, new Number[] { in }); |
| } |
| |
| /** |
| * @param in1 instance #1 of wanted Number class |
| * @param in2 instance #1 of wanted Number class |
| * @param out input number |
| * @return wanted Number |
| * @see #matchType(double,Number...) |
| */ |
| protected Number matchType(Number in1, Number in2, double out) |
| { |
| return matchType(out, new Number[] { in1, in2 }); |
| } |
| |
| /** |
| * Takes the original argument(s) and returns the resulting value as |
| * an instance of the best matching type (Integer, Long, or Double). |
| * If either an argument or the result is not an integer (i.e. has no |
| * decimal when rendered) the result will be returned as a Double. |
| * If not and the result is < -2147483648 or > 2147483647, then a |
| * Long will be returned. Otherwise, an Integer will be returned. |
| * @param out target number value |
| * @param in wanted Number classes |
| * @return wanted Number |
| */ |
| protected Number matchType(double out, Number... in) |
| { |
| //NOTE: if we just checked class types, we could miss custom |
| // extensions of java.lang.Number, and if we only checked |
| // the mathematical value, $math.div('3.0', 1) would render |
| // as '3'. To get the expected result, we check what we're |
| // concerned about: the rendered string. |
| |
| // first check if the result is even a whole number |
| boolean isIntegral = (Math.rint(out) == out); |
| if (isIntegral) |
| { |
| for (Number n : in) |
| { |
| if (n == null) |
| { |
| break; |
| } |
| else if (hasFloatingPoint(n.toString())) |
| { |
| isIntegral = false; |
| break; |
| } |
| } |
| } |
| |
| if (!isIntegral) |
| { |
| return new Double(out); |
| } |
| else if (out > Integer.MAX_VALUE || out < Integer.MIN_VALUE) |
| { |
| return Long.valueOf((long)out); |
| } |
| else |
| { |
| return Integer.valueOf((int)out); |
| } |
| } |
| |
| /** |
| * @param value target value |
| * @return wether it contains a decimal separator (non locale-aware for now - TODO) |
| */ |
| protected boolean hasFloatingPoint(String value) |
| { |
| return value.indexOf('.') >= 0; |
| } |
| |
| // ------------------------- Aggregation methods ------------------ |
| |
| /** |
| * Get the sum of the values from a list |
| * |
| * @param collection A collection containing Java beans |
| * @param field A Java Bean field for the objects in <i>collection</i> that |
| * will return a number. |
| * @return The sum of the values in <i>collection</i>. |
| */ |
| public Number getTotal(Collection collection, String field) |
| { |
| if (collection == null || field == null) |
| { |
| return null; |
| } |
| double result = 0; |
| // hold the first number and use it to match return type |
| Number first = null; |
| try |
| { |
| for (Iterator i = collection.iterator(); i.hasNext();) |
| { |
| Object property = PropertyUtils.getProperty(i.next(), field); |
| Number value = toNumber(property); |
| // skip over nulls (i.e. treat them as 0) |
| if (value != null) |
| { |
| if (first == null) |
| { |
| first = value; |
| } |
| result += value.doubleValue(); |
| } |
| } |
| return matchType(first, result); |
| } |
| catch (Exception e) |
| { |
| return null; |
| } |
| } |
| |
| /** |
| * Get the average of the values from a list |
| * |
| * @param collection A collection containing Java beans |
| * @param field A Java Bean field for the objects in <i>collection</i> that |
| * will return a number. |
| * @return The average of the values in <i>collection</i>. |
| */ |
| public Number getAverage(Collection collection, String field) |
| { |
| Number result = getTotal(collection, field); |
| if (result == null) |
| { |
| return null; |
| } |
| double avg = result.doubleValue() / collection.size(); |
| return matchType(result, avg); |
| } |
| |
| /** |
| * Get the sum of the values from a list |
| * |
| * @param array An array containing Java beans |
| * @param field A Java Bean field for the objects in <i>array</i> that |
| * will return a number. |
| * @return The sum of the values in <i>array</i>. |
| */ |
| public Number getTotal(Object[] array, String field) |
| { |
| return getTotal(Arrays.asList(array), field); |
| } |
| |
| /** |
| * Get the sum of the values from a list |
| * |
| * @param array A collection containing Java beans |
| * @param field A Java Bean field for the objects in <i>array</i> that |
| * will return a number. |
| * @return The sum of the values in <i>array</i>. |
| */ |
| public Number getAverage(Object[] array, String field) |
| { |
| return getAverage(Arrays.asList(array), field); |
| } |
| |
| /** |
| * Get the sum of the values |
| * |
| * @param collection A collection containing numeric values |
| * @return The sum of the values in <i>collection</i>. |
| */ |
| public Number getTotal(Collection collection) |
| { |
| if (collection == null) |
| { |
| return null; |
| } |
| |
| double result = 0; |
| // grab the first number and use it to match return type |
| Number first = null; |
| for (Iterator i = collection.iterator(); i.hasNext();) |
| { |
| Number value = toNumber(i.next()); |
| if (value == null) |
| { |
| //FIXME? or should we ignore this and keep adding? |
| return null; |
| } |
| if (first == null) |
| { |
| first = value; |
| } |
| result += value.doubleValue(); |
| } |
| return matchType(first, result); |
| } |
| |
| /** |
| * Get the average of the values |
| * |
| * @param collection A collection containing number values |
| * @return The average of the values in <i>collection</i>. |
| */ |
| public Number getAverage(Collection collection) |
| { |
| Number result = getTotal(collection); |
| if (result == null) |
| { |
| return null; |
| } |
| double avg = result.doubleValue() / collection.size(); |
| return matchType(result, avg); |
| } |
| |
| /** |
| * Get the sum of the values |
| * |
| * @param array An array containing number values |
| * @return The sum of the values in <i>array</i>. |
| */ |
| public Number getTotal(Object... array) |
| { |
| return getTotal(Arrays.asList(array)); |
| } |
| |
| /** |
| * Get the average of the values |
| * |
| * @param array An array containing number values |
| * @return The sum of the values in <i>array</i>. |
| */ |
| public Number getAverage(Object... array) |
| { |
| return getAverage(Arrays.asList(array)); |
| } |
| |
| /** |
| * Get the sum of the values |
| * |
| * @param values The list of double values to add up. |
| * @return The sum of the arrays |
| */ |
| public Number getTotal(double... values) |
| { |
| if (values == null) |
| { |
| return null; |
| } |
| |
| double result = 0; |
| for (double value : values) { |
| result += value; |
| } |
| return new Double(result); |
| } |
| |
| /** |
| * Get the average of the values in an array of double values |
| * |
| * @param values The list of double values |
| * @return The average of the array of values |
| */ |
| public Number getAverage(double... values) |
| { |
| Number total = getTotal(values); |
| if (total == null) |
| { |
| return null; |
| } |
| return new Double(total.doubleValue() / values.length); |
| } |
| |
| /** |
| * Get the sum of the values |
| * |
| * @param values The list of long values to add up. |
| * @return The sum of the arrays |
| */ |
| public Number getTotal(long... values) |
| { |
| if (values == null) |
| { |
| return null; |
| } |
| |
| long result = 0; |
| for (long value : values) { |
| result += value; |
| } |
| return Long.valueOf(result); |
| } |
| |
| /** |
| * Get the average of the values in an array of long values |
| * |
| * @param values The list of long values |
| * @return The average of the array of values |
| */ |
| public Number getAverage(long... values) |
| { |
| Number total = getTotal(values); |
| if (total == null) |
| { |
| return null; |
| } |
| double avg = total.doubleValue() / values.length; |
| return matchType(total, avg); |
| } |
| |
| } |