it-roy-ru.com

Как рассчитать медиану массива?

Я пытаюсь вычислить общее, среднее значение и медиану массива, который заполняется вводом, полученным текстовым полем. Мне удалось вычислить общее и среднее, я просто не могу заставить медиану работать. Я думаю, что массив должен быть отсортирован, прежде чем я смогу сделать это, но я не уверен, как это сделать. Это проблема, или есть другая, которую я не нашел? Вот мой код:

import Java.applet.Applet;
import Java.awt.Graphics;
import Java.awt.*;
import Java.awt.event.*;

public class whileloopq extends Applet implements ActionListener
{
    Label label;
    TextField input;
    int num;
    int index;
    int[] numArray = new int[20];
    int sum;
    int total;
    double avg;
    int median;



    public void init ()
    {
        label = new Label("Enter numbers");
        input = new TextField(5);
        add(label);
        add(input);
        input.addActionListener(this);
        index = 0;
    }

    public void actionPerformed (ActionEvent ev)
    {
        int num = Integer.parseInt(input.getText());
        numArray[index] = num;
        index++;
        if (index == 20)
        input.setEnabled(false);
            input.setText("");
        sum = 0;
        for (int i = 0; i < numArray.length; i++)
        {
            sum += numArray[i];
        }
        total = sum;
        avg = total / index;

        median = numArray[numArray.length/2];



        repaint();

    }



    public void Paint (Graphics graf)
    {



        graf.drawString("Total   = " + Integer.toString(total), 25, 85);
        graf.drawString("Average = " + Double.toString(avg), 25, 100);
        graf.drawString("Median = " + Integer.toString(median), 25, 115);



    }
}
31
Will

Класс Arrays в Java имеет статическую функцию сортировки, которую вы можете вызвать с помощью Arrays.sort(numArray).

Arrays.sort(numArray);
double median;
if (numArray.length % 2 == 0)
    median = ((double)numArray[numArray.length/2] + (double)numArray[numArray.length/2 - 1])/2;
else
    median = (double) numArray[numArray.length/2];
54
lynnyi

Сортировка массива не нужна и неэффективна. Существует вариант алгоритма QuickSort ( QuickSelect ), который имеет среднее время выполнения O (n); если вы сортируете первым, вы переходите к O (n log n). На самом деле он находит n-й наименьший элемент в списке; для медианы вы просто используете n = половину длины списка. Давайте назовем это quickNth (list, n).

Концепция заключается в том, чтобы найти n-е наименьшее, выберите значение «pivot». (Точно, как вы выбираете, это не критично; если вы знаете, что данные будут полностью случайными, вы можете взять первый элемент в списке.) 

Разделите оригинальный список на три меньших списка: 

  • Один со значениями меньше, чем стержень.
  • Один со значениями, равными оси. 
  • И один со значениями больше, чем стержень. 

Затем у вас есть три случая:

  1. «Меньший» список содержит> = n элементов. В этом случае вы знаете, что nth самый маленький находится в этом списке. Вернуть quickNth (меньше, n).
  2. Меньший список имеет <n элементов, но сумма длин меньших и равных списков имеет> = n элементов. В этом случае nth равен любому элементу в списке «равно»; все готово.
  3. n больше, чем сумма длин меньшего и равного списков. В этом случае вы можете пропустить эти два параметра и соответственно изменить n. Вернуть quickNth (больше, n - длина (меньше) - длина (равно)).

Готово.

Если вы не уверены, что данные полностью случайные, вам нужно быть более изощренным в выборе основной точки. Взяв медиану первого значения в списке, последнее значение в списке и одно посередине между двумя, работает довольно хорошо.

Если вы очень не повезло с выбором шарниров, и вы всегда можете выбрать наименьшее или наибольшее значение как ваш стержень, это занимает O времени (п ^ 2); это плохо. Но это также очень маловероятно, если вы выберете свою опору с приличным алгоритмом.

Пример кода QuickSelect

30
Bruce Feist

Если вы хотите использовать какую-либо внешнюю библиотеку, используйте Apache commons math library , используя ее, вы можете вычислить Median .
Дополнительные методы и использование смотрите в Документация по API

import org.Apache.commons.math3.*;
.....
......
........
//calculate median
public double getMedian(double[] values){
 Median median = new Median();
 double medianValue = median.evaluate(values);
 return medianValue;
}
.......

Обновление 

Рассчитать в программе 

Как правило, медиана рассчитывается с использованием следующих двух формул приведено здесь

Если n нечетно, то Median (M) = значение ((n + 1)/2) -го элемента элемента.
Если n четное, то Медиана (M) = значение [((n)/2) -го элемента + + ((n)/2 + 1)-го элемента]/2

В вашей программе у вас есть numArray, сначала вам нужно отсортировать массив с помощью Arrays # sort

Arrays.sort(numArray);
int middle = numArray.length/2;
int medianValue = 0; //declare variable 
if (numArray.length%2 == 1) 
    medianValue = numArray[middle];
else
   medianValue = (numArray[middle-1] + numArray[middle]) / 2;
6
Aniket Kulkarni
Arrays.sort(numArray);
int middle = ((numArray.length) / 2);
if(numArray.length % 2 == 0){
 int medianA = numArray[middle];
 int medianB = numArray[middle-1];
 median = (medianA + medianB) / 2;
} else{
 median = numArray[middle + 1];
}

Правка: Первоначально у меня medianB был установлен в middle+1 в массивах четной длины, это было неправильно из-за начального числа массивов в 0. Я обновил его, чтобы использовать middle-1, который является правильным и должен работать правильно для массива с четной длиной.

4
Walls

Попробуйте сначала отсортировать массив. Затем, после сортировки, если массив имеет четное количество элементов, среднее значение средних двух - это медиана, если оно имеет нечетное число, средний элемент - это медиана.

2
mjgpy3

Я смотрел на те же проблемы статистики. Подход, который вы думаете, это хорошо, и это сработает. (Ответ на сортировку был дан) 

Но в случае, если вы заинтересованы в производительности алгоритма, я думаю, что есть пара алгоритмов, которые имеют лучшую производительность, чем просто сортировка массива, один ( QuickSelect ) обозначен ответом @ bruce-feist и очень хорошо объяснен.

[Реализация Java: https://discuss.leetcode.com/topic/14611/Java-quick-select ]

Но есть вариант этого алгоритма с именем медиана медиан , вы можете найти хорошее объяснение по этой ссылке: http://austinrochford.com/posts/2013-10-28-median- of-medians.html

Java реализация этого: - https://stackoverflow.com/a/27719796/957979

1
cesaregb

Вчера я столкнулся с подобной проблемой. Я написал метод с использованием дженериков Java, чтобы вычислить медианное значение для каждой коллекции чисел; Вы можете применить мой метод к коллекциям Doubles, Integer, Floats и возвращает double. Пожалуйста, учтите, что мой метод создает другую коллекцию, чтобы не изменять оригинальную . Я также предоставляю тест, получайте удовольствие. ;-)

public static <T extends Number & Comparable<T>> double median(Collection<T> numbers){
    if(numbers.isEmpty()){
        throw new IllegalArgumentException("Cannot compute median on empty collection of numbers");
    }
    List<T> numbersList = new ArrayList<>(numbers);
    Collections.sort(numbersList);
    int middle = numbersList.size()/2;
    if(numbersList.size() % 2 == 0){
        return 0.5 * (numbersList.get(middle).doubleValue() + numbersList.get(middle-1).doubleValue());
    } else {
        return numbersList.get(middle).doubleValue();
    }

}

Фрагмент кода JUnit:

/**
 * Test of median method, of class Utils.
 */
@Test
public void testMedian() {
    System.out.println("median");
    Double expResult = 3.0;
    Double result = Utils.median(Arrays.asList(3.0,2.0,1.0,9.0,13.0));
    assertEquals(expResult, result);
    expResult = 3.5;
    result = Utils.median(Arrays.asList(3.0,2.0,1.0,9.0,4.0,13.0));
    assertEquals(expResult, result);
}

Пример использования (рассмотрим имя класса Utils):

List<Integer> intValues = ... //omitted init
Set<Float> floatValues = ... //omitted init
.....
double intListMedian = Utils.median(intValues);
double floatSetMedian = Utils.median(floatValues);

Примечание: мой метод работает с коллекциями, вы можете конвертировать массивы чисел в список чисел, как указано здесь

1
Fabiano Tarlao

Вы можете найти хорошее объяснение на https://www.youtube.com/watch?time_continue=23&v=VmogG01IjYc

Идея в том, чтобы использовать 2 кучи, а именно одну максимальную кучу и среднюю кучу.

class Heap {
private Queue<Integer> low = new PriorityQueue<>(Comparator.reverseOrder());
private Queue<Integer> high = new PriorityQueue<>();

public void add(int number) {
    Queue<Integer> target = low.size() <= high.size() ? low : high;
    target.add(number);
    balance();
}

private void balance() {
    while(!low.isEmpty() && !high.isEmpty() && low.peek() > high.peek()) {
        Integer lowHead= low.poll();
        Integer highHead = high.poll();
        low.add(highHead);
        high.add(lowHead);
    }
}

public double median() {
    if(low.isEmpty() && high.isEmpty()) {
        throw new IllegalStateException("Heap is empty");
    } else {
        return low.size() == high.size() ? (low.peek() + high.peek()) / 2.0 : low.peek();
    }
}

}

1
Abhijit Gaikwad

Используйте Arrays.sort , а затем возьмите средний элемент (если число n элементов в массиве нечетно) или возьмите среднее значение двух средних элементов (если n четное).

  public static long median(long[] l)
  {
    Arrays.sort(l);
    int middle = l.length / 2;
    if (l.length % 2 == 0)
    {
      long left = l[middle - 1];
      long right = l[middle];
      return (left + right) / 2;
    }
    else
    {
      return l[middle];
    }
  }

Вот некоторые примеры:

  @Test
  public void evenTest()
  {
    long[] l = {
        5, 6, 1, 3, 2
    };
    Assert.assertEquals((3 + 4) / 2, median(l));
  }

  @Test
  public oddTest()
  {
    long[] l = {
        5, 1, 3, 2, 4
    };
    Assert.assertEquals(3, median(l));
  }

И если ваш ввод Collection, вы можете использовать Google Guava , чтобы сделать что-то вроде этого:

public static long median(Collection<Long> numbers)
{
  return median(Longs.toArray(numbers)); // requires import com.google.common.primitives.Longs;
}
1
Hbf
public int[] data={31, 29, 47, 48, 23, 30, 21
        , 40, 23, 39, 47, 47, 42, 44, 23, 26, 44, 32, 20, 40};

public double median()
    {
        Arrays.sort(this.data);
        double result=0;
        int size=this.data.length;


        if(size%2==1)
        {
            result=data[((size-1)/2)+1];
            System.out.println(" uneven size : "+result);
        }
        else
        { 
            int middle_pair_first_index =(size-1)/2;
            result=(data[middle_pair_first_index+1]+data[middle_pair_first_index])/2;
            System.out.println(" Even size : "+result);
        }

        return result;
    }
0
N_E

Проверьте методы Arrays.sort:

http://docs.Oracle.com/javase/6/docs/api/Java/util/Arrays.html

Вы также должны действительно абстрагироваться от нахождения медианы в своем собственном методе и просто вернуть значение вызывающему методу. Это сделает тестирование вашего кода намного проще.

0
aglassman
Arrays.sort(numArray);
return (numArray[size/2] + numArray[(size-1)/2]) / 2;
0
i_use_the_internet