4

私はこれで私の髪を引っ張っています.他の人のJava経験が問題に光を当てることができるかどうかを見てみたいと思いました. 私が書いた大量のプログラム コードがありますが、それ自体がより大きなプロジェクト内にあるため、単純に投稿することはできません。ただし、問題の概要を説明します...

問題: 私のコードは、シミュレーションから予測可能な結果を​​返しません。シミュレーションが実行されるたびに、さまざまな統計が記録されます。コードは同じ (!) にもかかわらず、生成される結果は実行ごとに異なります。

私が確信していることは問題ではありません(ただし、「落とし穴」があると思われる場合は大声で言ってください):

  • 乱数ジェネレーターが使用されますが、毎回同じ値がシードされます。
  • プログラムはシングル スレッドであるため、競合状態は問題になりません。
  • 動作は、デバッグ モード、スタンドアロン jar、および IDE からの通常の実行の両方で発生します (私は Eclipse を使用しています)。
  • 静的メンバーは、リスト内のオブジェクト間で使用されます。for-each コンストラクトが使用されますが、これは毎回同じ順序で実行する必要があります。
  • 前述のリストをソートする場合、 Collections.sort() が使用されるため、安定している必要があります (リストは同じ順序で並べる必要があります)。

私がここで見落としているかもしれない何かを誰かが思いつくことができますか? これは現時点では計り知れないようです!ありがとう!

4

6 に答える 6

3

すべての場所で作成したランダムのインスタンスを使用していることを確認しますか?Math.random()の呼び出しでは、独自のRandomインスタンスを使用することに注意してください。

于 2010-03-02T18:58:11.770 に答える
3

オブジェクトとオブジェクトの両方 をオーバーライドした(またはカスタムコンパレータを作成した)と想定しています。オブジェクトで乱数が使用されている場合、それは並べ替えの基準ではありませんよね?equals()hashCode()

また、これらのアイテムを並べ替える場合は、それらをHashMapまたはHashSetに配置します(これらの構造は順序を保持しません)。代わりにTreeSetまたはTreeMapを使用してください。

于 2010-03-02T18:58:16.547 に答える
2

アプリに多くのトレースを追加してから、ログを調べて分岐点を確認してください。

于 2010-03-02T18:50:24.297 に答える
1

InTraceというツールを使用して、Java コードの実行を追跡できます。これにより、プログラムの異なる実行間で詳細な制御フローを比較できます。

注: InTrace は、私が作成した無料のオープン ソース ツールです。

于 2011-06-19T19:52:42.917 に答える
0

ガベージコレクションが発生する可能性はありますか? これにより、タイミングに少しランダム性が追加される場合があります。Sun JVM を使用している場合、GC 情報を出力するオプションがいくつかあります。

    -XX:-PrintGC ガベージ コレクションでメッセージを出力します。管理可能。
    -XX:-PrintGCDetails ガベージ コレクションで詳細を出力します。管理可能。            
                               (1.4.0 で導入されました。)
    -XX:-PrintGCTimeStamps ガベージ コレクション時のタイムスタンプを出力します。管理可能
                               (1.4.0 で導入されました。)

詳細はこのページから抜粋。

jstatを使用して、何が起こっているかに関するパフォーマンス統計を取得することもできます。

于 2010-03-02T19:38:03.833 に答える
0

あなたのコードを知らずに見分けるのは難しいですが、ここで私が探し始めるいくつかのポイントがあります.

個々のクラスがすべて期待どおりに機能することを確認します。つまり、少なくともコア クラスを単体テストする必要があります。

追加のチェックのためにすべてのプライベート メソッドに assert-Statements を挿入して、ヘルパー メソッドに渡すデータが有効であることを確認します。(パブリック メソッドで assert を使用しないでください。そこでは例外を使用してください)。

ロギング (log4j などを使用している場合は DEBUG レベル) または単純な System.out.println() ステートメントをすべての重要なポイントに追加して、値が変化する場所を把握します。これは、データが実際にコードをどのように流れるかを理解するのに役立ちます。

Eclipse を使用しているため、デバッガーを使用してコードをステップ実行し、予期しないデータの変更を監視します。

誤った仮定をチェックします。これは、たとえば、純粋な true/false チェックではない条件の else ブロックのビジネス ロジックです。たとえば、GUI でこのようなコードをよく見かけます。

if (button == OK_BUTTON) {
    doOkButton();
} else {
    doCancelBotton(); // VERY dangerous. could be any Button
}

これを修正

if (button == OK_BUTTON) {
    doOkButton();
} else if (button == CANCEL_BUTTON) {
    doCancelBotton();
} else {
    assert false : "Oops, a new button?"
}

あなたは乱数発生器を使用していると言いました。毎回正しいものを使用していて、出力にランダム性が追加されていませんか? 一体何のために使っているのですか?

時間ベースのものを使用していますか?たとえば System.currentTimeMillies?

正しいコレクションを使用していますか? すべてがソートおよび順序付けされているわけではなく、すべての要素を調べようとすると、アプリケーションが実行されるたびに異なる結果になる可能性があります。

コレクションで使用するすべてのクラスに適切な equals() と hashCode() があることを確認します

オートボクシングを使用していますか?比較は慎重に

 new Integer(5) == new Integer(5) 

値ではなく 2 つのオブジェクト参照を比較するため、false です。

Integer i = new Integer(5);
i++;

i++ で新しいオブジェクトを作成します。これらは見つけるのが難しく、ほとんどの場合、プリミティブとコレクションを操作すると、オートボクシングが発生します。

仮定を無効にする可能性のあるサードパーティのライブラリを使用していますか (競合状態など)

コードの静的分析には、FindBugsなどのツールを使用します。何かヒントになるかもしれません。

それが私が始めるところです。幸運を!

于 2010-03-02T20:07:11.237 に答える