简体   繁体   English

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

[英]Calculate average of and huge long array

I'm trying to calculate the average of many (more than 200) long (primitive type) values stored in an array. 我正在尝试计算存储在数组中的许多(超过200) long (原始类型)值的平均值。 Usally you add all the numbers and divide it by the number of the values. 通常,您添加所有数字并将其除以值的数量。 But this is not possible in this case since there is no primitive datatype in Java capable of holding such a lare number, isn't it? 但是在这种情况下这是不可能的,因为Java中没有原始数据类型能够保存这样一个数字,不是吗? Will java.math.BigInteger help here? 请问java.math.BigInteger在这里有帮助吗?

Yes it will help you. 是的,它会帮助你。 An BigInteger can be as big as you want. BigInteger可以根据需要大小。 Till there is not enough RAM. 直到没有足够的RAM。

With BigInteger bigInt = BigInteger.valueOf(long); 使用BigInteger bigInt = BigInteger.valueOf(long); you can convert the Long to an BigInteger . 您可以将Long转换为BigInteger

And an BigInteger is immutable. BigInteger是不可变的。 So if you divide it like this bigInt = bigInt.divide(BigInteger.valueOf(200)); 所以,如果你像这样划分bigInt = bigInt.divide(BigInteger.valueOf(200)); You have to reassign it. 你必须重新分配它。

A more precise option would be the method BigInteger.divideAndRemainder() . 更精确的选项是BigInteger.divideAndRemainder()方法。

Kai has a very good answer, but I'll just throw out there that if you know the exact number of values you are trying to average (and you do, since you said it was an array), then you can divide each value by N before adding them all up. Kai有一个非常好的答案,但我只是扔掉那里,如果你知道你试图平均的值的确切数量(并且你这样做,因为你说它是一个数组),那么你可以将每个值除以添加它们之前 N。 Then you would never exceed the limit of long . 然后你永远不会超过long的限制。

Example: the limit of long is roughly 9.22e18, so let's do an average near that limit: 示例: 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;
    }

(The Math.round() calls are needed since exponential notation numbers are doubles in Java.) (需要Math.round()调用,因为指数表示法数字在Java中是双倍的。)

If you know that the sum of all the long values in your array / list will never exceed the Long.MAX_VALUE value, you can use the following to calculate the average: 如果您知道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();

But if you're unsure about the sum of your list, and that it can even exceed the maximum limit that long primitive provides, then use the following method to calculate the average: 但是如果您不确定列表的总和,并且它甚至可以超过长基元提供的最大限制,那么使用以下方法计算平均值:

// 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()));

This technique works from Java 8 and following imports are required: 此技术适用于Java 8,需要以下导入:

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.stream.LongStream;
  • An average of a long is unlikely to be a long , so you need to decide for a type to keep your result. 平均long不太long ,所以你需要决定一个类型来保持你的结果。 BigDecimal (not a BigInteger though) could be a good choice. BigDecimal (不是BigInteger )可能是个不错的选择。 You will probably need to define the accuracy of your result as well. 您可能还需要定义结果的准确性。
  • Use a smarter algorithm to compute averages on massive collections. 使用更智能的算法来计算大量集合的平均值。 I do not have a definitive choice for you, but you could try something like this: 我没有明确的选择,但您可以尝试这样的事情:

    1. initialise the value for your result as BigDecimal zero; 将结果的值初始化为BigDecimal零;
    2. compute a sum of next M elements and divide it by N where N is the total number of elements and M<N . 计算下一个M元素的总和并将其除以N ,其中N是元素的总数并且M<N The choice of M depends on the scale of your values and the accuracy your want to achive -- the larger the better, but think of your original problem; M的选择取决于你的价值观的规模和你想要达到的准确性 - 越大越好,但想想你原来的问题;
    3. add this value to the result and go back to step 2 until all elements are used up 将此值添加到结果中并返回步骤2,直到所有元素都用完为止

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM