【问题标题】:Mean, Median and Mode均值、中值和众数
【发布时间】:2017-01-11 06:33:19
【问题描述】:

您好,我的模态值代码有问题。这是我的代码:

public class basicStatistics {
 public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    int n = in.nextInt();
    int[] arr = new int[n];
    int[] arrCount = new int[n];
    int maxCount = 0;
    double median = 0.0, mean = 0.0;
    for(int i = 0; i < n; i++) {
        arr[i] = in.nextInt();
        mean = mean + arr[i];
    }
    mean = mean/n;
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++){
            if(arr[i] == arr[j]){
                arrCount[i]++;
            }
        if(maxCount < arrCount[i])
            maxCount = i;
        }
    }
    Arrays.sort(arr);
    if(n%2 == 0) {
        median = arr[n/2] + arr[n/2-1]; 
        median = median/2;
    } else {
        median = arr[n/2];
    }
    System.out.printf("%.1f\n", mean);
    System.out.printf("%.1f\n", median);
    System.out.println(arr[maxCount]);
 }
}

问题是当输入如下时我无法正确获取模态值:http://pastebin.com/HCqTrimY 我使用了 pastebin,因为它输入了 2500 个数字。我的代码为 Mode 输出数组值 259 而不是 2184 但是如果输入是 n = 10 并且数字 = 64630 11735 14216 99233 14470 4978 73429 38120 51135 67060 我得到正确的模式值或其他情况。

我还想利用 Java8 结构将代码转换为更高效的代码。提前谢谢你!

【问题讨论】:

  • 你真的要测试if(arr[i] == arr[j]) if i==j 吗?
  • hmm.. 我在想我在第二次修订时删除了它。我将如何消除它?我之前在 if(arr[i]==arr[j]) { ... } 上方添加了一个 if(i != j) { ... }

标签: java java-7 mean median mode


【解决方案1】:

如果您想使用 Java 8,您可以使该代码更短。首先,mean:在这里你可以从你的int-array arr 创建一个stream,然后调用average 方法:

double mean = IntStream.of(arr).average().getAsDouble();

median 与您的代码中的几乎相同;我只是通过使用三元表达式 (... ? ... : ...) 而不是多行 if/else 将它放在更少的行上:

Arrays.sort(arr);
int len = arr.length;
double median = len % 2 == 0 ? (arr[len/2-1] + arr[len/2]) / 2. : arr[len/2];

mode 有点困难,最后但并非最不重要的一点是,您似乎需要最小的模式,以防最常出现多个数字。虽然您的双for-loop 方法也可以工作,但它具有二次复杂性,这可能成为更大数据集的问题。相反,您应该使用Map 来计算不同的数字。在 Java 8 中,这可以使用Collectors.groupingByCollectors.counting 轻松完成。然后,只需确定计数中的maxfilter 具有该计数的数字,并获得其中的min

Map<Integer, Long> counts = IntStream.of(arr).boxed()
        .collect(Collectors.groupingBy(x -> x, Collectors.counting()));
Long max = counts.values().stream().max(Comparator.naturalOrder()).get();
int mode = counts.entrySet().stream()
        .filter(e -> e.getValue().equals(max))
        .min(Comparator.comparing(Entry::getKey)).get().getKey();

【讨论】:

  • 谢谢你,我需要用更少的代码行来转换它,我是 lambda 新手,刚刚开始学习它。如果我的输入 = 10 并且数字是 64630 11735 14216 99233 14470 4978 73429 38120 51135 67060,我的模式不会返回正确答案。
  • @Cham 当我在该数据上使用它时,我得到4978。你得到了什么,什么应该是“正确的”模式? (在数学上,它们全部都是正确的。)
  • 最小的应该是4978,我的代码是11735。
  • @Cham 正如我所说,4978 是我使用该代码得到的。当您说您使用 your 代码获得 11735 时,您是指来自 my 答案的代码,还是来自 yours 的代码?
  • 我的代码我还没有把它转换成你的代码。我想了解是什么导致模态值不正确。
【解决方案2】:

“将其转换为 Java8 结构”是什么意思?使用像 mean += arr[i]; 这样的增量也会更有效。而不是 mean = mean + arr[i];

针对您的问题:试试这个:

int maxCount = 0;
final int[] arrCount = new int[n];
for(int i = 0; i < n; i++) {
    for(int j = 0; j < n; j++){
        if(i != j && arr[i] == arr[j])
            arrCount[i]++;
    }
    if(maxCount < arrCount[i])
        maxCount = i;
}

【讨论】:

  • 我刚刚找到了你的答案,它是我新问题的解决方案!谢谢!
【解决方案3】:

您好,我回答了我自己的问题。答案是把数组排序放在获取maxCount的方法上面:

    ...
    mean = mean/n;
    Arrays.sort(arr);
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++){
            if(arr[i] == arr[j]){
                arrCount[i]++;
            }
        if(maxCount < arrCount[i])
            maxCount = i;
        }
    }
    if(n%2 == 0) { ...

现在唯一的问题是将其转换为 Java8 结构。编辑:当我尝试输入 n = 10; 时出现了一个新问题;数字是 64630 11735 14216 99233 14470 4978 73429 38120 51135 67060 它没有正确获得模态值,它应该是 4978 它输出 11735。

编辑:要修复新错误,我必须在评估 if(arr[i] == arr[j]) {...} 之前添加此代码 if(i != j) {... }。

【讨论】:

  • 为什么模态值应该是 4978?所有值都同样频繁地出现(一次)。如果存在多个模态,函数应该返回最小的吗?
猜你喜欢
  • 1970-01-01
  • 2019-09-17
  • 2019-03-07
  • 2015-03-13
  • 1970-01-01
  • 1970-01-01
  • 2021-04-14
  • 2015-12-24
  • 2011-12-05
相关资源
最近更新 更多