2016-09-03 8 views
-1

Привет, У меня проблема с моими кодами по Модальному значению. Вот мой код:Среднее, медианное и режимное

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

Вопрос в том, что я не могу получить значение права Modal, когда вход это: http://pastebin.com/HCqTrimY я использовал Pastebin как это входы 2500 номеров. Мой код выводит значение массива 259 вместо 2184 для режима, однако, если вход равен n = 10, а числа = 64630 11735 14216 99233 14470 4978 73429 38120 51135 67060 Я получаю значение режима правильно или для другого сценария.

Я также хотел преобразовать код в более эффективный, используя структуру Java8. Заранее благодарю!

+1

Вы действительно хотите проверить 'if (arr [i] == arr [j])' if 'i == j'? –

+0

hmm .. Я думал о том, что я удалил его во второй ревизии. Как я могу его устранить? что я раньше был добавлен if if (i! = j) {...} выше if (arr [i] == arr [j]) {...} – Cham

ответ

0

Если вы хотите использовать Java 8, вы можете сделать этот код намного короче. Во-первых, mean: Здесь вы можете создать stream от вашего int -array arr, а затем просто вызовите 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.groupingBy и Collectors.counting. Затем просто определите цифры max, filter номера, которые имеют этот счет, и получите 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(); 
+0

Спасибо, что мне нужно было преобразовать его на меньшее количество строк кода, я новичок в лямбда и только начинаю изучать его. У меня проблема с режимом, в котором он не возвращает правильный ответ, если мой вход = 10 и цифры 64630 11735 14216 99233 14470 4978 73429 38120 51135 67060. – Cham

+0

@Cham Когда я использую его для этих данных, я получаю '4978', , Что вы получаете, и что должно быть «правильным» режимом? (Математически, они _all_ правильные.) –

+0

Это должно быть 4978 наименьшее, что я получаю с моим кодом - 11735. – Cham

0

Привет, я ответил на свою собственную проблему. Ответ поставить сортировку массива выше способом, чтобы получить 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. EDIT: возникает новая проблема, когда я попытался ввести n = 10; номера 64630 11735 14216 99233 14470 4978 73429 38120 51135 67060 он не получает правильное значение, которое должно быть 4978 оно выводит 11735.

EDIT: Чтобы исправить новую ошибку, мне пришлось добавить этот код, если (i! = j) {...} перед оценкой if (arr [i] == arr [j]) {...}.

+0

Почему модальное значение должно быть 4978? Все значения отображаются одинаково часто (один раз). Если существует несколько модалов, должна ли функция возвращать наименьшую? –

+0

правильный, он должен вернуть наименьшее! – Cham

0

Что вы подразумеваете под «преобразованием этого в структуру Java8»? Также было бы более эффективно использовать приращения, такие как mean + = arr [i]; вместо среднего = среднее + 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; 
} 
+0

Я только что нашел ваш ответ, и это решение моей новой проблемы! Спасибо! – Cham