質問

私は、数日からミリ秒に与えられた数を変換する方法を書いてます:

private long expireTimeInMilliseconds;
...
public void setExpireTimeInDays(int expireTimeInDays)
{
   expireTimeInMilliseconds = expireTimeInDays * 24 * 60 * 60 * 1000;
}

私は私が間違っていたかを把握するために苦労しました。今、私の質問: のように明らかにそのエラーますか?

修正方法:

private long expireTimeInMilliseconds;
...
public void setExpireTimeInDays(int expireTimeInDays)
{
   expireTimeInMilliseconds = ((long) expireTimeInDays) * 24 * 60 * 60 * 1000;
}
私が計算する前にlongに整数を変換しない場合は、

、私は完全に間違った結果を取得します。

役に立ちましたか?

解決

これは明白ですか?私はそれはあなたは、Javaを使用してきた、あなたがミリ秒に対処しなければならなかった回数をどのくらいに依存しますね。もちろん、それは約24日間まで大丈夫でなければなりません...

私は最大のヒントはSystem.currentTimeMillis()longを返すことをすべきだと思います。これは、ミリ秒数が大きく得ることができることは良い兆候です。あなたが設定している変数の型は、あまりにも良いヒントである必要があります。

もちろん、あなたがきたのあなたはint型で演算を行う場合には、結果がオーバーフローにラップアラウンドでintされることを知りました。それは十分に明らかだかどうかは、議論することができ、それはかなり無意味な議論になります。あなたは、オーバーフローのチェックを有効にした場合、C#では、あなたはかなり迅速にバグを発見したと思います - 。しかし、その後はない多くの開発者(実際に、私はない私はおそらく必要がありますが)それを行う

他のヒント

はい、それはあなたが前にそれをやった場合はかなり明白です。あなたは数字の文字列を参照してくださいいつでもあなたは自動的に整数オーバーフローエラーについて考え始める必要があるうち掛けました。 expireTimeInDaysは、あなたがオーバーフローエラーを考えるべきである以上24技術的には、をいつでもあなたがの整数で作業しているが、このようにそれらのグループを乗算することでなければなりませんこの場合、あなたは、オーバーフローに設定されています非常に大きな赤い旗ます。

あなたのオペランド変数とリテラルの数値はint型です。 intデータ型は、2 ^ 31 -1の最大値を有します。したがって、このような大規模な数字で、int型のデータ型は、見せかけの不正解に導くオーバーフローします。

あなたの最初の例では、int型は、長いだけの計算後のを発生する変数への代入上に昇格されます。計算の結果はintです。

第二の例では、長尺の計算の促進を引き起こし、長い第1オペランドをキャスト。この場合、計算結果は、プロモーションのために、長いです。 longデータ型は、あなたの計算のために十分な大きさ以上のものです。

あなたは、これはジョシュア・ブロックとニールGafter氏による「Javaののpuzzlers」で覆われていることを知って興味がある可能性があります。


<サブ>(ソース: javapuzzlers.com の)

あなたはその本の中で他の多くのJavaの落とし穴、トラップとコーナーケースがあります。

私がコメントを残しstarblueに同意します。番号にLを追加します。

いいえ、それは明らかではありません。

しかし、実際このようなバグを修正するいくつかのより多くの年後にあなたが整数オーバーフローについて非常に賢明になり、ちょうどそれについて考えずに正しいことを行う、私を信頼しています。

これは誰にでも起こっ何か。そんなに悪いコードの練習、無知かの間違い兆候ます。

ただ、他の回答に追加するには、私はそれが参考に過去にそのようpublic static final longMILLISECS_DAYなどの定数(MILLISECS_HOUR)を定義することが分かってきました。 はるかに読みやすく、便利ます。

これを書くための別の方法がある。

public void setExpireTimeInDays(int expireTimeInDays)
{
   expireTimeInMilliseconds = (long) expireTimeInDays * 24 * 60 * 60 * 1000;
}

または

public void setExpireTimeInDays(int expireTimeInDays)
{
   expireTimeInMilliseconds = expireTimeInDays * 24L * 60 * 60 * 1000;
}
あなたのコード上にFindBugsを使用する場合は、

それはこの正確な問題を検出します。 「アイキャスト:longにキャスト整数乗算の結果。」 FindBugsの例では、正確にあなたがやっていることです。ミリ秒単位での日数を計算します。

この問題は、私には、私はそれに走った初めて明らかではなかった。

いくつかの静的解析ツールのエラーのこれらのタイプを見つける(FindBugsの)があります。

コンピュータ上の数値数学は難しいことができます。操作事項の順序は、あなたが期待していない方法で、精度と正確さに影響を与えることができます。日付数学も驚くほど注意が必要です。多くの場合、それは自分で数学をやろうとしているのではなく、日付/カレンダールーチンを使用することをお勧めしますが、これらのルーチンは、Javaクラスライブラリで最高の設計されたものではありません。

私は私のミスを正当化しようとしていないんだけど、(計算はlong型の変数に代入された後)は、Javaコンパイラが長い計算する前にint型を促進するために十分にスマートだった場合、それは素晴らしいことです

ちなみに、私はC / C ++で作業するために使用し、それがCプログラムだった場合、私は同じ問題を抱えていたと思いますが、何年か前、私はこの種の操作をより慎重になって思います。

私は次の時間にもっと注意を払う(やPythonに切り替える)よ...:D

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top