2016-02-09 5 views
17

は、私はそれだけで走って停止するように見せかけなしに走った、intを長く変更すると実行が高速になるのはなぜですか?

int maxColl = 0; 
int maxLen = 0; 
for (int i = 2; i < 1000000; i++) { 
    int coll = i; 
    int len = 1; 
    while (coll != 1) { 
    if (coll % 2 == 0) { 
     coll = coll/2; 
    } else { 
     coll = 3 * coll + 1; 
    } 
    len++; 
    } 
    if (len > maxLen) { 
    maxLen = len; 
    maxColl = i; 
    } 
} 

トラブルだった... problem #14 from Project Eulerを解決しようとしていた、そして次のC#を書いていました。

問題の他の人の解決策を探した後、私はintの代わりにlongを使用していたことを除いて、非常によく似たものを見ました。私はこの問題に関係するすべての数値がintの範囲内にあるので、これがなぜ必要なのかわかりませんでしたが、とにかく試しました。

intをlongに変更すると、コードが2秒以上で実行されました。

誰でもこのことを私に説明できますか?

+0

intからlongに変更するだけで、その劇的な違いはありません。 whileループが壊れるのを防ぐオーバーフローがあると思われます。デバッガでそれを見て、どこかにオーバーフローがあるかどうかわからないかどうかを確認してください。 –

+0

通常、Int64はInt32より低速です。ここでオーバーフロー処理があり、Int32が遅くなる可能性があります。 – Ben

+0

@Ben除算といくつかの複雑な操作を除いて通常は同じ速度です。いくつかのシステムでは、符号/ゼロ拡張と64ビット値に変換するためのマスキングが必要なため、32ビット値での動作はさらに遅くなります。説明のためにありがとう –

答えて

25

iが113383に等しい場合、いくつかの点で3X + 1配列がそう3 * coll + 1オーバーフロー、intの最大値を超えて負になる:→827370449

113383→340150→...→1654740898→ -1812855948→-906427974→...

は最終的には、シーケンスは、負の数の次のサイクルで巻き取る:

...→-17→-50→-25→-74→-37→-110→-55→-164→-82→-41→-122→-61→-182→-91→-272 →-136→-68→-34→-17

このサイクルには1が含まれないため、ループは終了しません。

intの代わりにlongを使用すると、collは決してオーバーフローしません。

+1

ああ!私はそれを確認したと思った。なぜ私は他のいくつかの質問と同様の問題を抱えていた理由を説明します。 –

24

整数がオーバーフローしてマイナスになっています。
したがって、ループは決して実際に終了しません。
コードをcheckedブロックにラップすると、代わりにオーバーフロー例外が表示されます。

longは、必要な値を格納するのに十分な大きさなので、正常に動作します。

+1

あなたとマイケル劉が同時に来て、彼は少し説明があったので、私は彼を答えとして作っていますが、あなたもとても役に立ちました。どうもありがとう。 –

+2

@AvrohomYisroel公正であるために、SLAKsは2分速くなりました:) –

関連する問題