54

テキストフィールドが受け取った入力によって取り込まれた配列の合計、平均、および中央値を計算しようとしています。合計と平均を計算できましたが、中央値を機能させることができません。これを行う前に配列をソートする必要があると思いますが、これを行う方法がわかりません。これが問題ですか、それとも私が見つけられなかった別の問題がありますか? これが私のコードです:

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



    }
}
4

16 に答える 16

90

JavaのArraysクラスには静的ソート関数があり、これをで呼び出すことができます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];
于 2012-08-14T15:37:39.137 に答える
40

配列の並べ替えは不要で非効率的です。O(n) の平均実行時間を持つQuickSort ( QuickSelect ) アルゴリズムのバリエーションがあります。最初にソートすると、O(n log n) になります。実際には、リスト内で n 番目に小さい項目を見つけます。中央値の場合、n = リストの長さの半分を使用します。これを quickNth (list, n) としましょう。

概念は、n 番目に小さいものを見つけるために、「ピボット」値を選択することです。(正確にどのように選択するかは重要ではありません。データが完全にランダムであることがわかっている場合は、リストの最初の項目を取得できます。)

元のリストを 3 つの小さなリストに分割します。

  • ピボットより小さい値を持つもの。
  • ピボットと等しい値を持つもの。
  • そして、ピボットより大きい値を持つもの。

次に、3 つのケースがあります。

  1. 「小さい」リストには >= n 個の項目があります。その場合、n 番目に小さいものがそのリストにあることがわかります。quickNth(より小さい, n) を返します。
  2. 小さい方のリストには < n 個の項目がありますが、小さいリストと等しいリストの長さの合計は >= n 個の項目があります。この場合、n 番目は「等しい」リスト内の任意の項目と等しくなります。あなたは終わった。
  3. n は、小さいリストと等しいリストの長さの合計よりも大きくなります。その場合、基本的にこれら 2 つをスキップして、それに応じて n を調整できます。quickNth(より大きい、n - 長さ (小さい) - 長さ (等しい)) を返します。

終わり。

データが完全にランダムかどうかわからない場合は、ピボットの選択についてより洗練する必要があります。リストの最初の値、リストの最後の値、および 2 つの値の中間にある値の中央値を取得すると、かなりうまく機能します。

ピボットの選択に運が悪く、ピボットとして常に最小値または最大値を選択すると、O(n^2) 時間かかります。良くないね。ただし、まともなアルゴリズムでピボットを選択した場合、それはほとんどありません

サンプルコード:

import java.util.*;

public class Utility {
   /****************
   * @param coll an ArrayList of Comparable objects
   * @return the median of coll
   *****************/
   
   public static <T extends Number> double median(ArrayList<T> coll, Comparator<T> comp) {
      double result;
      int n = coll.size()/2;
      
      if (coll.size() % 2 == 0)  // even number of items; find the middle two and average them
         result = (nth(coll, n-1, comp).doubleValue() + nth(coll, n, comp).doubleValue()) / 2.0;
      else                      // odd number of items; return the one in the middle
         result = nth(coll, n, comp).doubleValue();
         
      return result;
   } // median(coll)
   
   

   /*****************
   * @param coll a collection of Comparable objects
   * @param n  the position of the desired object, using the ordering defined on the list elements
   * @return the nth smallest object
   *******************/
   
   public static <T> T nth(ArrayList<T> coll, int n, Comparator<T> comp) {
      T result, pivot;
      ArrayList<T> underPivot = new ArrayList<>(), overPivot = new ArrayList<>(), equalPivot = new ArrayList<>();
      
      // choosing a pivot is a whole topic in itself.
      // this implementation uses the simple strategy of grabbing something from the middle of the ArrayList.
      
      pivot = coll.get(n/2);
      
      // split coll into 3 lists based on comparison with the pivot
      
      for (T obj : coll) {
         int order = comp.compare(obj, pivot);
         
         if (order < 0)        // obj < pivot
            underPivot.add(obj);
         else if (order > 0)   // obj > pivot
            overPivot.add(obj);
         else                  // obj = pivot
            equalPivot.add(obj);
      } // for each obj in coll
      
      // recurse on the appropriate list
      
      if (n < underPivot.size())
         result = nth(underPivot, n, comp);
      else if (n < underPivot.size() + equalPivot.size()) // equal to pivot; just return it
         result = pivot;
      else  // everything in underPivot and equalPivot is too small.  Adjust n accordingly in the recursion.
         result = nth(overPivot, n - underPivot.size() - equalPivot.size(), comp);
         
      return result;
   } // nth(coll, n)
   
   
   
   public static void main (String[] args) {
      Comparator<Integer> comp = Comparator.naturalOrder();
      Random rnd = new Random();
      
      for (int size = 1; size <= 10; size++) {
         ArrayList<Integer> coll = new ArrayList<>(size);
         for (int i = 0; i < size; i++)
            coll.add(rnd.nextInt(100));
      
         System.out.println("Median of " + coll.toString() + " is " + median(coll, comp));
      } // for a range of possible input sizes
   } // main(args)
} // Utility
于 2015-03-03T00:56:33.420 に答える
12

外部ライブラリを使用する場合は、ここでApache commons math ライブラリを使用して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;
}
.......

アップデート

プログラムで計算する

一般に、中央値は、ここに示す次の 2 つの式を使用して計算されます。

n が奇数の場合、中央値 (M) = ((n + 1)/2) 番目の項目の値。
n が偶数の場合、中央値 (M) = [((n)/2) 番目のアイテム期間 + ((n)/2 + 1) 番目のアイテム期間]/2 の値

あなたのプログラムでは、まずArrays#sortnumArrayを使用して配列をソートする必要があります

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;
于 2013-11-08T06:36:55.310 に答える
4
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。これは正しく、偶数の長さの配列で正しく機能するはずです。

于 2012-08-14T15:38:13.567 に答える
2

使用Arrays.sortしてから中央の要素を取得するか (n配列内の要素の数が奇数の場合)、または中央の 2 つの要素の平均を取得します (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));
  }

入力が の場合、Google GuavaCollectionを使用して次のようなことを行うことができます。

public static long median(Collection<Long> numbers)
{
  return median(Longs.toArray(numbers)); // requires import com.google.common.primitives.Longs;
}
于 2013-05-19T16:34:59.290 に答える
2

最初に配列をソートしてみてください。次に、並べ替えた後、配列の要素数が偶数の場合は中央の 2 つの平均が中央値になり、奇数の場合は中央の要素が中央値になります。

于 2012-08-14T15:31:54.953 に答える
0

Arrays.sort メソッドを確認してください。

http://docs.oracle.com/javase/6/docs/api/java/util/Arrays.html

また、中央値の検索を独自のメソッドに抽象化し、呼び出し元のメソッドに値を返すだけにする必要があります。これにより、コードのテストがはるかに簡単になります。

于 2012-08-14T15:32:36.200 に答える