12

Java で捕食者と被食者のシミュレーションを少し書きました。ルールが非常に複雑で混沌としたシステムになったとしても、使用される手法は単純です。

  • 基本的なデータ型に関する算術演算と決定
  • 外部ライブラリなし
  • 外部システムは含まれていません
  • 同時実行は発生しません
  • 現在の時刻または日付を使用しない

したがって、システムを同じパラメーターで初期化すると、同じ結果が出力されるはずだと思ったのですが、そうではなく、なぜだろうかと思います。

それに関するいくつかの考え: 私のアプリケーションはRandoms を使用しますが、そのテストではそれらをすべて指定された値で初期化するため、私の理解では、実行ごとに同じ出力を同じ順序で作成する必要があります。

私はSets を繰り返し処理していますが、 a が繰り返される順序Setが定義されていないことを知っています。Setしかし、同じ順序で同じ値が入力された a が、複数の実行で異なる動作をする理由はわかりません。そうですか?

Sをたくさん使っていfloatます。1 + 1 = 1.9999999999725 のデータ型は、私には常に疑わしいものですが、それらの動作が私にとって奇妙であっても、常に同じように奇妙であるはずです。ではない?

ガベージ コレクションは決定論的ではありませんが、デストラクタに依存しない限り安全です。

上記のように、実際の使用時間に応じて同時実行性やデータ型はありません。

簡単な例でその動作を再現することはできません。しかし、私のコードを調べてみると、予測できないものは何も見えません。上記の私の仮定は間違っていますか?私が見逃している可能性のあるアイデアはありますか?

これが私の仮定を検証するためのテストです。

public static void main(String[] args) {
    Random r = new Random(1);
    Set<Float> s = new HashSet<Float>();
    for (int i = 0; i < 1000000; i++) {
        s.add(r.nextFloat());
    }

    float ret = 1;
    int cnt = 0;
    for (Float f : s) {
        float multiply = 0.3f;
        if (cnt++ % 2 == 0) {
            multiply = 0.7f;
        }
        float f2 = (f * multiply);
        ret += f2;
    }

    System.out.println(ret);
}

私にとっては常に242455.25になります。

4

2 に答える 2

20

Java で決定論的なプログラムを作成できます。非決定論の可能性のある原因を排除する必要があるだけです。

実際のコードとその決定論の具体的な証拠を見ずに、何が非決定論を引き起こしているのかを知ることは困難です。

非決定論的な動作の原因となる可能性のあるライブラリメソッドはいくつもあります...使用方法によって異なります。

たとえば、Object.hashcode()(インスタンスで初めて呼び出されたときに) によって返される値は非決定論的です。そして、それはハッシュを使用するすべてのライブラリに浸透します。要素クラスがオーバーライドされていない場合、要素を反復するときにHashSetorの要素が返される順序に確実に影響を与える可能性があります。HashMaphashcode()

乱数ジェネレーターは、決定論的である場合とそうでない場合があります。それらが疑似乱数であり、固定シードで初期化されている場合、それぞれによって生成される数値のシーケンスは決定論的になります。

浮動小数点演算は決定論的でなければなりません。算術式への入力の任意の (固定) セットについて、結果は常に同じである必要があります。(浮動小数点演算の決定性が JLS によって保証されているかどうかはわかりませんが、実際にそうなったとしたら非常に奇妙です。たとえば、壊れたハードウェアで実行しているのと同じです。)


FOLLOWUP ...strictfpと非決定論。

JLS 15.4によると:

「FP 厳密ではない式の中で、中間結果を表すために拡張された指数範囲を使用する実装にいくらかの余裕が与えられます。大まかに言えば、正味の効果は、次のような状況で計算が「正しい答え」を生成する可能性があることです。 float 値セットまたは double 値セットを排他的に使用すると、オーバーフローまたはアンダーフローが発生する可能性があります。」

これは、実装が非 FP 厳密式でどれだけの「余裕」を持っているかを正確に示しているわけではありません。ただし、その余裕は、非決定論的な動作を許可することには及ばないと考えていました。特定のプラットフォーム上の JIT コンパイラーは常に同じ式に対して同等のネイティブ コードを生成し、そのコードは決定論的であると考えていました。(ハードウェア自体に非決定論的な浮動小数点がない限り、非決定論の理由はわかりません。)非決定論の他の考えられる原因は、JITコンパイルおよび解釈されたコードの動作が異なる可能性があることです。しかし、率直に言って、それが起こるのを許すのは「ばかげている」と思います...そして、私たちはそれを聞いたことがあると思います.

したがって、非 FP 厳密な式の評価は理論的には非決定論的である可能性がありますが、実際に発生するという明確な証拠がない限り、これを軽視する必要があると思います。

(プラットフォームの違いではなく、実際の非決定論について話していることに注意してください。)

于 2013-07-13T02:06:49.857 に答える
11

私はセットを反復していますが、セットが反復される順序が定義されていないことを知っています。しかし、同じ順序で同じ値が入力された Set が、複数の実行で異なる動作をする理由はわかりません。そうですか?

できる。実装は、たとえば、メモリ内のオブジェクトの場所を基になるハッシュ テーブルへのキーとして自由に使用できます。これは、ガベージ コレクションがいつ実行されるかによって異なります。

于 2013-07-13T02:08:51.660 に答える