计算平均值和巨大的长数组

时间:2014-01-06 14:35:24

标签: java arrays performance numbers

我正在尝试计算存储在数组中的许多(超过200个)long(基本类型)值的平均值。通常,您添加所有数字并将其除以值的数量。但是在这种情况下这是不可能的,因为Java中没有原始数据类型能够保存这样一个数字,不是吗? java.math.BigInteger会在这里提供帮助吗?

4 个答案:

答案 0 :(得分:4)

是的,它会对你有所帮助。 BigInteger可以根据需要大小。直到没有足够的RAM。

使用BigInteger bigInt = BigInteger.valueOf(long);,您可以将Long转换为BigInteger

BigInteger是不可变的。所以如果你这样划分bigInt = bigInt.divide(BigInteger.valueOf(200));你必须重新分配它。

更精确的选择是方法BigInteger.divideAndRemainder()

答案 1 :(得分:2)

Kai有一个非常好的答案,但我只是扔掉那里,如果你知道你想要平均的值的确切数量(并且你这样做,因为你说它是一个数组),那么你可以划分之前的每个值将它们全部添加起来。那么你永远不会超过long的限制。

示例:long的限制大约是9.22e18,所以让我们做一个接近该限制的平均值:

    long[] arr = {Math.round(5e18), Math.round(9e18)};
    double avg = 0.0d;
    int size = arr.length;
    for (int i = 0; i < size; i++) {
        long l = arr[i];
        double tmp = l/(double)size;
        avg += tmp;
    }

(由于指数表示法编号在Java中是双倍的,因此需要Math.round()次调用。)

答案 2 :(得分:2)

如果您知道array / list中所有长值的总和不会超过Long.MAX_VALUE值,则可以使用以下内容计算平均值:

// For long type array
long[] array = ...;
double average = LongStream.of(array).average().getAsDouble();

// For long type list
List<Long> list = ...;
double average = list.stream().mapToLong(n -> n).average().getAsDouble();

但如果您不确定列表的总和,并且它甚至可能超过长基元提供的最大限制,那么请使用以下方法计算平均值:

// For long type array
long[] array = ...;
BigInteger sum = LongStream.of(array).mapToObj(BigInteger::valueOf).reduce((x, y) -> x.add(y)).get();
BigDecimal average = new BigDecimal(sum).divide(BigDecimal.valueOf(array.length));

// For long type list
List<Long> list = ...;
BigInteger sum = list.stream().map(BigInteger::valueOf).reduce((x, y) -> x.add(y)).get();
BigDecimal average = new BigDecimal(sum).divide(BigDecimal.valueOf(list.size()));

此技术适用于Java 8,需要进行以下导入:

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.stream.LongStream;

答案 3 :(得分:1)

  • long的平均值不大可能是long,因此您需要决定是否保留结果类型。 BigDecimal(不是BigInteger)可能是个不错的选择。您可能还需要定义结果的准确性。
  • 使用更智能的算法计算大量集合的平均值。我没有明确的选择,但您可以尝试这样的事情:

    1. 将结果的值初始化为BigDecimal零;
    2. 计算下一个M元素的总和,并将其除以N,其中N是元素的总数,M<NM的选择取决于您的价值观的规模和您想要达到的准确性 - 越大越好,但要考虑您原来的问题;
    3. 将此值添加到结果中并返回步骤2,直到所有元素都用完为止