Calculating average of an array list?

后端 未结 11 835
天涯浪人
天涯浪人 2020-11-29 09:04

I\'m trying to use the below code to calculate the average of a set of values that a user enters and display it in a jTextArea but it does not work properly. Sa

相关标签:
11条回答
  • sum += i;
    

    You're adding the index; you should be adding the actual item in the ArrayList:

    sum += marks.get(i);
    

    Also, to ensure the return value isn't truncated, force one operand to double and change your method signature to double:

    return (double)sum / marks.size();
    
    0 讨论(0)
  • 2020-11-29 09:39

    If using Java8 you can get the average of the values from a List as follows:

        List<Integer> intList = Arrays.asList(1,2,2,3,1,5);
    
        Double average = intList.stream().mapToInt(val -> val).average().orElse(0.0);
    

    This has the advantage of having no moving parts. It can be easily adapted to work with a List of other types of object by changing the map method call.

    For example with Doubles:

        List<Double> dblList = Arrays.asList(1.1,2.1,2.2,3.1,1.5,5.3);
        Double average = dblList.stream().mapToDouble(val -> val).average().orElse(0.0);
    

    NB. mapToDouble is required because it returns a DoubleStream which has an average method, while using map does not.

    or BigDecimals:

    @Test
    public void bigDecimalListAveragedCorrectly() {
        List<BigDecimal> bdList = Arrays.asList(valueOf(1.1),valueOf(2.1),valueOf(2.2),valueOf(3.1),valueOf(1.5),valueOf(5.3));
        Double average = bdList.stream().mapToDouble(BigDecimal::doubleValue).average().orElse(0.0);
        assertEquals(2.55, average, 0.000001);
    }
    

    using orElse(0.0) removes problems with the Optional object returned from the average being 'not present'.

    0 讨论(0)
  • 2020-11-29 09:40
    List.stream().mapToDouble(a->a).average()
    
    0 讨论(0)
  • 2020-11-29 09:40

    You can use standard looping constructs or iterator/listiterator for the same :

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

    If using Java 8, you could use Stream or IntSream operations for the same :

    OptionalDouble avg = list.stream().mapToInt(Integer::intValue).average();
    System.out.println("Average = " + avg.getAsDouble());
    

    Reference : Calculating average of arraylist

    0 讨论(0)
  • 2020-11-29 09:47

    When the number is not big, everything seems just right. But if it isn't, great caution is required to achieve correctness.

    Take double as an example:

    If it is not big, as others mentioned you can just try this simply:

    doubles.stream().mapToDouble(d -> d).average().orElse(0.0);
    

    However, if it's out of your control and quite big, you have to turn to BigDecimal as follows (methods in the old answers using BigDecimal actually are wrong).

    doubles.stream().map(BigDecimal::valueOf).reduce(BigDecimal.ZERO, BigDecimal::add)
           .divide(BigDecimal.valueOf(doubles.size())).doubleValue();
    

    Enclose the tests I carried out to demonstrate my point:

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

    As for Integer or Long, correspondingly you can use BigInteger similarly.

    0 讨论(0)
提交回复
热议问题