Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 计算数组列表的平均值?_Java_Arrays_Average - Fatal编程技术网

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