2011-07-09 8 views
3

以下のコードは、配列のローカル最大値を正しく検出しますが、ローカル最小値を見つけることができません。私はミニマを見つけるための最良の方法を見つけるためにウェブ検索をしました、そして、私はそれらの検索に基づいて、以下の正しい方法を使用していると思います。しかし、下のコードには、数日かけて何度も各行に何度も行った後、まだ見ていないバグがあります。ローカル検索最小値

変数startXとendXは、コードがローカル最小値/最大値を見つけなければならないユーザー選択ウィンドウを定義します。 startXとendXの値を操作すると、下のコードは常に、選択したウィンドウの最初のインデックスとして最小値を出力します。これは、最小値を検索するためにウィンドウ内のインデックスを反復していないことを示します。

誰でもこのバグを見つけて、以下のコードを修正してローカルの最小値を見つける方法を教えてください。

class LocalMinMax { 
static double[] pts; 
static int visiblePoints=5000; 
static int startX = 200; 
static int endX = 700; 

public static void main (String[] args) { 
    int lastX2 = 0; 
    int maxWidth = 800; 
    double hstep = (double) maxWidth/visiblePoints; 
    int maxHeight = 400; 
    pts = new double[visiblePoints]; 
    double max = Double.NEGATIVE_INFINITY; 
    double min = Double.POSITIVE_INFINITY; 
    int minIndex = -1; 
    int maxIndex = -1; 
    for (int i = 0; i < visiblePoints; i++){ 
     pts[i] = (double) ((((Math.sin(.009*i))*(Math.cos(.004*i))) * (maxHeight/3) * .95) + (maxHeight/2)); 
     int x2 = (int) (i * hstep); 
     if(x2>=startX){ 
      int sectionStartIndex = i; 
      int sectionEndIndex = (int)(endX/hstep); 
       for(int k=sectionStartIndex;k<sectionEndIndex;k++){ 
        if(min>pts[k]){ 
         min = pts[k]; 
         minIndex = x2; 
         System.out.println("minIndex, min, pts["+k+"]: , x2 are: "+minIndex+", "+min+", "+pts[k]+", "+x2); 
        } 
        if(max<pts[k]){ 
         max = pts[k]; 
         maxIndex = x2; 
        }}} 
     if(lastX2!=x2){ 
      lastX2=x2; 
      if(x2==startX){ 
       int width = endX - startX; 
       System.out.println("WINDOW: width, startX, endX are: "+width+", "+startX+", "+endX); 
       }}} 
    int maxVal = (int)max; 
    int minVal = (int)min; 
    System.out.println("LOCAL MAX: maxIndex, maxVal are: "+maxIndex+", "+maxVal); 
    System.out.println("LOCAL MIN: minIndex, minVal are: "+minIndex+", "+minVal); 
    }} 
+0

これはdo-my-homeworkの質問のように聞こえます。あなたはグーグルの「javaの配列の最大要素を見つける」と考えましたか?あなたは素晴らしい結果を得るでしょう。 – chahuistle

+0

@chahuistle、キーワード候補をありがとう。はい、私は最大/分をjavaで見つける方法を知っています。そして、はい、私はウェブ検索を行っています。混乱は、paintComponent()コードとの統合に関するものです。私のコードを見ると、min/maxを見つけるための正しい方法を使用し、グローバルmin/maxが正しく検出されることがわかります。また、私のコードのローカルminを見つけるために働かないメソッドの1つは、Web検索で見つかったメソッドから直接得られます。しかし、はい、私はまたあなたが提案したキーワードからの検索結果を見るでしょう。ありがとうございました。 – CodeMed

+0

問題は、 'double min = Double.POSITIVE_INFINITY'を評価した直後に、' if(min> pts [k]) '行が最初の反復でminをゼロに設定しているということです。この関数のすべての値は正の値なので、 'if(min> pts [k])'は決して真と評価されないので、ウィンドウの開始インデックスのパネルの最上部に最小矩形マーカーが残ります。最初のパスでゼロになるのを止めることができれば、このバグを取り除くことができます。何か案は? – CodeMed

答えて

2

一つのアプローチは、以下に示すように、sectionStartIndex..sectionEndIndex窓を通して後方スキャンすることです。それは解決策ではありませんが、緑色の矩形が最小値を追跡するにつれて上下に移動するのを表示します。

for (int k = sectionStartIndex; k < sectionEndIndex; k++) { 
    int j = sectionEndIndex - k; 
    if (min > pts[j]) { 
     System.out.println("minIndex, min, pts[" + j + "]: " 
      + minIndex + ", " + min + ", " + pts[j]); 
     min = pts[j]; 
     minIndex = x2Count; 
    } 
    if (max < pts[k]) { 
     max = pts[k]; 
     maxIndex = x2Count; 
    } 
} 

補足:配列の初期化をループから外すことは、以下に示すように1つのアプローチです。スケーリング操作で除数のdoubleを使用することに注意してください。

さらに深刻な問題は、別のドメインで関数をサンプリングしながら、あるドメインの関数を評価することです。モデル(実数はdoubleで表されます)からビュー(マウス座標)を分離します。 *scale*関数のように、2つの間の座標を変換するメソッドを導入してください。hereモデルがマウスの動きに応じて機能を評価するようにします。証明された場合にのみ最適化する。

 
Local: maxIndex, maxVal: 200, 326 
Local: minIndex, minVal: 200, 79 
class LocalMinMax { 

    static double[] pts; 
    static int visiblePoints = 5000; 
    static int startX = 200; 
    static int endX = 700; 

    public static void main(String[] args) { 
     int lastX2 = 0; 
     int maxWidth = 800; 
     double hstep = maxWidth/(double) visiblePoints; 
     int maxHeight = 400; 
     pts = new double[visiblePoints]; 
     for (int i = 0; i < pts.length; i++) { 
      pts[i] = (((Math.sin(.009 * i)) * (Math.cos(.004 * i))) 
       * (maxHeight/3d) * .95) + (maxHeight/2d); 
     } 
     double max = Double.NEGATIVE_INFINITY; 
     double min = Double.POSITIVE_INFINITY; 
     int minIndex = -1; 
     int maxIndex = -1; 
     for (int i = 0; i < visiblePoints; i++) { 
      int x2 = (int) (i * hstep); 
      if (x2 >= startX) { 
       int sectionStartIndex = i; 
       int sectionEndIndex = (int) (endX/hstep); 
       for (int k = sectionStartIndex; k < sectionEndIndex; k++) { 
        if (min > pts[k]) { 
         min = pts[k]; 
         minIndex = x2; 
         //System.out.println("minIndex, min, pts[" + k + "], x2: " 
         //+ minIndex + ", " + min + ", " + pts[k] + ", " + x2); 
        } 
        if (max < pts[k]) { 
         max = pts[k]; 
         maxIndex = x2; 
         //System.out.println("maxIndex, max, pts[" + k + "], x2: " 
         //+ maxIndex + ", " + max + ", " + pts[k] + ", " + x2); 
        } 
       } 
      } 
      if (lastX2 != x2) { 
       lastX2 = x2; 
       if (x2 == startX) { 
        int width = endX - startX; 
       } 
      } 
     } 
     int maxVal = (int) max; 
     int minVal = (int) min; 
     System.out.println("Local: maxIndex, maxVal: " + maxIndex + ", " + maxVal); 
     System.out.println("Local: minIndex, minVal: " + minIndex + ", " + minVal); 
    } 
} 
+0

ご協力いただきありがとうございます。それは本当に私の問題を解決するものではありませんが、あなたが投資した時間を感謝します。問題を分離したと思うので(上記参照)、私は明日もう一度この時間を過ごすことができるときに、より少ないコード量で問題を再現しようとします。もしその練習が私を解決に導かないなら、私は別の日かそこらに再度フレームされた質問を掲示するでしょう。 – CodeMed

+0

私は上記のコードの改訂版を再投稿しました。これは、問題をより簡単でより簡単なセグメントに分離して、デバッグしやすくする必要があります。あなたは今、バグを見ることができますか? – CodeMed

+0

ありがとうございます。私は明日のあなたの提案と一緒に働き、重要な更新や結論があるときに返信します。 – CodeMed

2

機能f(x) = sin(ax) + cos(bx)二倍differentiable、別のアプローチは、分析的に最小値と最大値を見つけることである(少なくとも)です。最初の導関数がゼロであれば、関数はローカルextremumになります。 2次導関数の符号は、極値が最小値か最大値かを示します。

+0

これを考えて書く時間をとってくれてありがとう、ありがとう。私のデータはデータ収集装置によって時系列に記録されています。私はちょうど 'f(x)= sine(ax)* cos(bx)'を投稿に使用したので、読者にデータファイルをダウンロードする必要はありませんでした。シヌソイドはデバッグに十分な最大値と最小値を持っています。 – CodeMed

+0

ああ、それは理にかなっています。実行時に安定したデータセットを使用すると、問題が単純化されます。それが配列または適切な 'Collection'に格納されている場合、検索はO(1)でなければなりません。 – trashgod

+0

O(1)はどういう意味ですか? – CodeMed

関連する問題