Java 计算数组列表的平均值?
我试图使用下面的代码计算用户输入的一组值的平均值,并将其显示在Java 计算数组列表的平均值?,java,arrays,average,Java,Arrays,Average,我试图使用下面的代码计算用户输入的一组值的平均值,并将其显示在jTextArea中,但它不能正常工作。比如说,用户输入7、4和5,程序在显示5.3时显示1作为平均值 ArrayList <Integer> marks = new ArrayList(); Collections.addAll(marks, (Integer.parseInt(markInput.getText()))); private void analyzeButtonActionPerformed
jTextArea
中,但它不能正常工作。比如说,用户输入7、4和5,程序在显示5.3时显示1作为平均值
ArrayList <Integer> marks = new ArrayList();
Collections.addAll(marks, (Integer.parseInt(markInput.getText())));
private void analyzeButtonActionPerformed(java.awt.event.ActionEvent evt) {
analyzeTextArea.setText("Class average:" + calculateAverage(marks));
}
private int calculateAverage(List <Integer> marks) {
int sum = 0;
for (int i=0; i< marks.size(); i++) {
sum += i;
}
return sum / marks.size();
}
ArrayList marks=new ArrayList();
Collections.addAll(marks,(Integer.parseInt(markInput.getText()));
已执行私有void分析按钮操作(java.awt.event.ActionEvent evt){
analyzeTextArea.setText(“班级平均:+calculateAverage(分数));
}
专用整数计算范围(列表标记){
整数和=0;
对于(int i=0;i
代码有什么问题
sum += i;
您正在添加索引;您应该在ArrayList
中添加实际项目:
sum += marks.get(i);
另外,为了确保返回值不被截断,请强制一个操作数为double
,并将方法签名更改为double
:
return (double)sum / marks.size();
public static BigDecimal calculateAverage(final List<Integer> values) {
int sum = 0;
if (!values.isEmpty()) {
for (final Integer v : values) {
sum += v;
}
return new BigDecimal(sum).divide(new BigDecimal(values.size()), 2, RoundingMode.HALF_UP);
}
return BigDecimal.ZERO;
}
使用double表示总和,否则您将进行整数除法,并且不会得到任何小数:
private double calculateAverage(List <Integer> marks) {
if (marks == null || marks.isEmpty()) {
return 0;
}
double sum = 0;
for (Integer mark : marks) {
sum += mark;
}
return sum / marks.size();
}
当您拥有增强的for循环时,为什么要使用带有索引的笨拙for循环
private double calculateAverage(List <Integer> marks) {
Integer sum = 0;
if(!marks.isEmpty()) {
for (Integer mark : marks) {
sum += mark;
}
return sum.doubleValue() / marks.size();
}
return sum;
}
private双重计算范围(列表标记){
整数和=0;
如果(!marks.isEmpty()){
用于(整数标记:标记){
总和+=分数;
}
返回sum.doubleValue()/marks.size();
}
回报金额;
}
更新:
正如其他几个人已经指出的那样,使用Java 8及以上版本的Streams会变得更加简单:
private double calculateAverage(List <Integer> marks) {
return marks.stream()
.mapToDouble(d -> d)
.average()
.orElse(0.0)
}
private双重计算范围(列表标记){
return marks.stream()
.mapToDouble(d->d)
.average()
.orElse(0.0)
}
对于Java 8,它是:
因此,您的平均值是average.getAsDouble()
这里的版本使用了
BigDecimal
而不是double
:
return (double)sum / marks.size();
public static BigDecimal calculateAverage(final List<Integer> values) {
int sum = 0;
if (!values.isEmpty()) {
for (final Integer v : values) {
sum += v;
}
return new BigDecimal(sum).divide(new BigDecimal(values.size()), 2, RoundingMode.HALF_UP);
}
return BigDecimal.ZERO;
}
公共静态BigDecimal calculateAverage(最终列表值){
整数和=0;
如果(!values.isEmpty()){
用于(最终整数v:值){
总和+=v;
}
返回新的BigDecimal(sum).divide(新的BigDecimal(values.size()),2,RoundingMode.HALF_UP);
}
返回BigDecimal.ZERO;
}
正确快速地计算列表的平均值
:
private双重计算范围(列表标记){
长和=0;
用于(整数标记:标记){
总和+=分数;
}
返回marks.isEmpty()?0:1.0*sum/marks.size();
}
此解决方案考虑到:
- 句柄溢出
- 不要像Java8流那样分配内存
- 不要使用慢速BigDecimal
它可以直接用于List,因为任何List包含的int小于2^31,并且可以使用long作为累加器
PS
实际上foreach分配内存-您应该在任务关键部件中使用旧式for()循环从Java8开始您可以从以下列表中获得值的平均值:
List<Integer> intList = Arrays.asList(1,2,2,3,1,5);
Double average = intList.stream().mapToInt(val -> val).average().orElse(0.0);
使用orElse(0.0)
可以消除从average
返回的可选对象“不存在”的问题。
Stats.meanOf(numericList);
您可以使用标准循环构造或迭代器/listiterator进行相同的操作:
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
double sum = 0;
Iterator<Integer> iter1 = list.iterator();
while (iter1.hasNext()) {
sum += iter1.next();
}
double average = sum / list.size();
System.out.println("Average = " + average);
OptionalDouble avg = list.stream().mapToInt(Integer::intValue).average();
System.out.println("Average = " + avg.getAsDouble());
参考资料:当数字不大时,一切似乎都正常。但如果不是,则需要非常小心才能实现正确性
以双倍为例:
如果它不是很大,正如其他人提到的,您可以简单地尝试一下:
doubles.stream().mapToDouble(d -> d).average().orElse(0.0);
但是,如果它超出了您的控制范围,并且非常大,您必须按如下方式转到BigDecimal(使用BigDecimal的旧答案中的方法实际上是错误的)
附上我为证明我的观点而进行的测试:
@Test
public void testAvgDouble() {
assertEquals(5.0, getAvgBasic(Stream.of(2.0, 4.0, 6.0, 8.0)), 1E-5);
List<Double> doubleList = new ArrayList<>(Arrays.asList(Math.pow(10, 308), Math.pow(10, 308), Math.pow(10, 308), Math.pow(10, 308)));
// Double.MAX_VALUE = 1.7976931348623157e+308
BigDecimal doubleSum = BigDecimal.ZERO;
for (Double d : doubleList) {
doubleSum = doubleSum.add(new BigDecimal(d.toString()));
}
out.println(doubleSum.divide(valueOf(doubleList.size())).doubleValue());
out.println(getAvgUsingRealBigDecimal(doubleList.stream()));
out.println(getAvgBasic(doubleList.stream()));
out.println(getAvgUsingFakeBigDecimal(doubleList.stream()));
}
private double getAvgBasic(Stream<Double> doubleStream) {
return doubleStream.mapToDouble(d -> d).average().orElse(0.0);
}
private double getAvgUsingFakeBigDecimal(Stream<Double> doubleStream) {
return doubleStream.map(BigDecimal::valueOf)
.collect(Collectors.averagingDouble(BigDecimal::doubleValue));
}
private double getAvgUsingRealBigDecimal(Stream<Double> doubleStream) {
List<Double> doubles = doubleStream.collect(Collectors.toList());
return doubles.stream().map(BigDecimal::valueOf).reduce(BigDecimal.ZERO, BigDecimal::add)
.divide(valueOf(doubles.size()), BigDecimal.ROUND_DOWN).doubleValue();
}
@测试
公共无效测试vgdouble(){
资产质量(5.0,getAvgBasic(2.0,4.0,6.0,8.0)流),1E-5;
List doubleList=newarraylist(Arrays.asList(Math.pow(10308)、Math.pow(10308)、Math.pow(10308)、Math.pow(10308));
//Double.MAX_值=1.7976931348623157e+308
BigDecimal doubleSum=BigDecimal.0;
for(双d:双列表){
doubleSum=doubleSum.add(新的BigDecimal(d.toString());
}
out.println(doubleSum.divide(valueOf(doubleList.size()).doubleValue());
println(getAvgUsingRealBigDecimal(doubleList.stream());
out.println(getAvgBasic(doubleList.stream());
println(getAvgUsingFakeBigDecimal(doubleList.stream());
}
私有双getAvgBasic(流双流){
返回doubleStream.mapToDouble(d->d.average().orElse(0.0);
}
私有双getAvgUsingFakeBigDecimal(流双流){
返回doubleStream.map(BigDecimal::valueOf)
.collect(收集器.averagingDouble(BigDecimal::doubleValue));
}
私有双getAvgUsingRealBigDecimal(流双流){
List doubles=doubleStream.collect(Collectors.toList());
返回doubles.stream().map(BigDecimal::valueOf).reduce(BigDecimal.ZERO,BigDecimal::add)
.divide(valueOf(doubles.size()),BigDecimal.ROUND_DOWN)。doubleValue();
}
对于Integer
或Long
,相应地,您可以类似地使用biginger
您不是在求和标记,而是在求和数组索引i
。因为他使用的是列表,所以您应该使用sum+=marks.get(i)代码>在返回之前将其转换为双精度将更干净,这样当标记是一个非常大的列表时,就不会出现任何浮点错误。关于Java 8 API,需要导入哪些内容?@eactor在上面的示例中,不需要额外导入。我会检查标记中的marks.size()==0,因为如果t,这将除以零
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);
double sum = 0;
Iterator<Integer> iter1 = list.iterator();
while (iter1.hasNext()) {
sum += iter1.next();
}
double average = sum / list.size();
System.out.println("Average = " + average);
OptionalDouble avg = list.stream().mapToInt(Integer::intValue).average();
System.out.println("Average = " + avg.getAsDouble());
List.stream().mapToDouble(a->a).average()
doubles.stream().mapToDouble(d -> d).average().orElse(0.0);
doubles.stream().map(BigDecimal::valueOf).reduce(BigDecimal.ZERO, BigDecimal::add)
.divide(BigDecimal.valueOf(doubles.size())).doubleValue();
@Test
public void testAvgDouble() {
assertEquals(5.0, getAvgBasic(Stream.of(2.0, 4.0, 6.0, 8.0)), 1E-5);
List<Double> doubleList = new ArrayList<>(Arrays.asList(Math.pow(10, 308), Math.pow(10, 308), Math.pow(10, 308), Math.pow(10, 308)));
// Double.MAX_VALUE = 1.7976931348623157e+308
BigDecimal doubleSum = BigDecimal.ZERO;
for (Double d : doubleList) {
doubleSum = doubleSum.add(new BigDecimal(d.toString()));
}
out.println(doubleSum.divide(valueOf(doubleList.size())).doubleValue());
out.println(getAvgUsingRealBigDecimal(doubleList.stream()));
out.println(getAvgBasic(doubleList.stream()));
out.println(getAvgUsingFakeBigDecimal(doubleList.stream()));
}
private double getAvgBasic(Stream<Double> doubleStream) {
return doubleStream.mapToDouble(d -> d).average().orElse(0.0);
}
private double getAvgUsingFakeBigDecimal(Stream<Double> doubleStream) {
return doubleStream.map(BigDecimal::valueOf)
.collect(Collectors.averagingDouble(BigDecimal::doubleValue));
}
private double getAvgUsingRealBigDecimal(Stream<Double> doubleStream) {
List<Double> doubles = doubleStream.collect(Collectors.toList());
return doubles.stream().map(BigDecimal::valueOf).reduce(BigDecimal.ZERO, BigDecimal::add)
.divide(valueOf(doubles.size()), BigDecimal.ROUND_DOWN).doubleValue();
}