我正在尝试计算存储在数组中的许多(超过200个)long
(基本类型)值的平均值。通常,您添加所有数字并将其除以值的数量。但是在这种情况下这是不可能的,因为Java中没有原始数据类型能够保存这样一个数字,不是吗? java.math.BigInteger
会在这里提供帮助吗?
答案 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
)可能是个不错的选择。您可能还需要定义结果的准确性。使用更智能的算法计算大量集合的平均值。我没有明确的选择,但您可以尝试这样的事情:
BigDecimal
零; M
元素的总和,并将其除以N
,其中N
是元素的总数,M<N
。 M
的选择取决于您的价值观的规模和您想要达到的准确性 - 越大越好,但要考虑您原来的问题;