[英]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;
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:
我没有明确的选择,但您可以尝试这样的事情:
BigDecimal
zero; BigDecimal
零; 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
的选择取决于你的价值观的规模和你想要达到的准确性 - 越大越好,但想想你原来的问题;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.