1

下面的代码效果很好,但我想添加一种方法来计算数组列表中整数的频率。例如:90-99 频率:3.... 80-89 频率 6

最好的方法是什么?我应该做一个计算++每个变量的if语句吗?

import java.io.*;
import java.lang.Math;
import java.util.*;
import java.text.DecimalFormat;

public class gradeSorter{

public static void main(String[] args) throws IOException {
{
DecimalFormat fmt = new DecimalFormat("0.000");
Scanner scanner = new Scanner(new File("grades.dat"));
double average;
double deviation;
double sum = 0;
int number = 0;
int newnumber = 0;
ArrayList<Integer> element = new ArrayList<Integer>();



while (scanner.hasNextInt())
{
element.add(scanner.nextInt());


}
for (int item : element){
        sum += item;
        System.out.println(item);
}

average = sum / element.size();

for (int i = 0; i < element.size(); i++)
{ 
newnumber += Math.pow((element.get(i) - average),2);

}


deviation = Math.sqrt(newnumber / (element.size()));




System.out.println("The average of these grades is : " + fmt.format(average));

System.out.println("The standard deviation of these grades is: " + fmt.format(deviation));  


}
}
}

----jGRASP exec: javagradeSorter

51
52
55
57
58
61
62
63
66
66
66
70
72
73
74
75
75
77
77
78
79
81
82
84
86
87
88
91
94
97
The average of these grades is : 73.233
The standard deviation of these grades is: 12.288

 ----jGRASP: operation complete.
4

4 回答 4

4

首先使用一个与您期望的最大值一样大的整数数组。由于这看起来像等级,也许我们可以假设您将获得的最大值是 100?如果是这样,这样的代码就可以了。

int[] freqMap = new int[100];
for(int i=0;i<list.size();i++){
    int indexValue = list.get(i);
    freqMap[indexValue]++;
}

看看这个并思考。因此,当进入 3 级时,我们获取第 3 个索引处的值,并将其递增。如果这种情况发生 10 次,我们的频率数组中的前4 个值将如下所示:

0 0 0 10

这是因为数组是 0 索引的。这里索引 3 的频率是 10。

编辑:

迭代结构以获得特定范围的频率。这是微不足道的。我将在这里演示:

//the frequency aggregate for the range 80-90
int freqFor80To90 = 0;
for(int i=80; i<90; i++){
    freqFor80To90+=freqMap[i];
}
System.out.println("The frequency for 80-90 is "+freqFor80To90);

就堆而言,存储所有数字的频率稍微贵一些,但与使用原始数据集计算整个范围的频率相比,您可以更快地查询许多不同的范围。

我提供的解决方案为您提供了一个结构freqMap, 来查询频率范围。这就是我在上面的代码示例中所做的;查询结构以获取特定范围的频率。

其他解决方案为您提供了包含整个范围频率的数组,这是完全有效的。然而,我的解决方案提供了更大的灵活性,因为它以更多的内存为代价,提供了对原始数据集的更精细视图。

于 2013-08-07T20:45:58.253 回答
1

创建一个 size 的数组10,它保存每个范围内数字的频率:

int[] rangeFrequency = new int[10];

现在,对于 range - 中的所有数字[0,9],频率将进入索引 0。对于 range [10, 19],频率将进入索引 1,依此类推......

现在的重点是如何获得所有这些范围的索引?就是这样:

伪代码:

for each element in list
    bucket = element / 10   // For range [0-9], this will give index = 0
                           // For range [10-19], this will give index = 1
    rangeFrequence[bucket] += 1;

代码:

int[] rangeFrequency = new int[10];

for (int elem: element) {
    int bucket = elem / 10;
    rangeFrequency[bucket] += 1;
}

// Print frequency from array:
for (int i = 0; i < rangeFrequency.length; ++i) {
    System.out.print("Frequency in range : [" + i * 10 + ", " + 
                                                 (i * 10 + 9) + ") --> ");
    System.out.println(rangeFrequency[i]);
}

请注意,您需要注意ArrayIndexOutOfBounds,当您grade < 0 || grade >= 100的 ,上述程序将崩溃。

于 2013-08-07T20:53:45.223 回答
1

您可以为此使用整数数组:

int[] counters = new int[NUMBER_OF_BUCKETS];

while (scanner.hasNextInt()) {
  int n = scanner.nextInt();

  // Determine which bucket this int should be in:
  int bucket = determineBucket(n);

  //Count the integer in the appropriate bucket:
  counters[bucket]++;
}

determineBucket()方法接受一个数字并决定应将其计入哪个存储桶(例如,存储桶只是一组数字,在您的情况下,存储桶的范围为 80-89)。对存储桶进行编码的最简单方法如下:

private static int determineBucket(int n) {
  if(80 <= n && n < 90) {
    return 0;
  } else if(90 <= n && n < 100) {
    return 1;
  } else if(...) {
    ...
  }
}

如果您实际上是在长度为 10 的范围内对数字进行分组,那么您可以比前面的代码做得更好,但我不确定您要做什么。

于 2013-08-07T20:58:55.243 回答
0

这里

java.util.Collections has the method:
public static int frequency(Collection<?> c, Object o)

“返回指定集合中等于指定对象的元素数。”

于 2013-08-07T21:15:51.117 回答