9

のより高速な (そして正しい) バージョンのように見えるこのコードに欠点はありますjava.lang.Math.roundか?

public static long round(double d) {

    if (d > 0) {
        return (long) (d + 0.5d);
    } else {
        return (long) (d - 0.5d);
    }
}

これは、Java では長いものに切り捨てるとゼロに丸められるという事実を利用しています。

4

3 に答える 3

15

組み込みメソッドが処理する特殊なケースがいくつかありますが、コードは処理しません。ドキュメントから:

  • 引数が の場合NaN、結果は 0 です。
  • 引数が負の無限大または の値以下の値であるInteger.MIN_VALUE場合、結果は の値と等しくなりますInteger.MIN_VALUE
  • 引数が正の無限大または の値以上の値であるInteger.MAX_VALUE場合、結果は の値と等しくなりますInteger.MAX_VALUE
于 2009-11-17T18:19:56.410 に答える
6

私はこれをテストしてきましたが、ここではまだ説明されていない1つの重要な潜在的な欠点があります。それは、丸めタイブレーク方法を変更していることです。

Math.round()「ラウンドハーフアップ」ルールをround()実装しますが、メソッドは「ゼロからラウンドハーフアウェイ」ルールを実装します。

例えば:

  • Math.round(-0.5d)=>0L
  • Your.round(-0.5d)=>-1L

これはあなたにとって問題かもしれないし、そうでないかもしれませんがMath.round()、NaNと無限の考慮事項がすでに概説された後でも、上記の方法はのドロップイン代替ではないことを理解する必要があります。

別の関連する質問:Javaでの負の数の丸め

パフォーマンスに関しては、上記の方法がよりも大幅に高速であることは間違いありませんMath.round()。ランダムに生成された正の値と負の値の場合、約35%の時間で実行されます。タイトループでこのメソッドを呼び出す場合、これは価値のある最適化になる可能性があります。おそらく分岐予測を使用しているCPUのために、正の値のみが与えられた場合はさらに良くなります(実行時間の25%) 。

Math.round()最終的にはネイティブJNI呼び出しによって実装されますが、これがパフォーマンスの違いの原因である可能性があります。このSun/Oracleのバグは、j6u22に純粋なJavaバージョンがある可能性があることを示唆していますが、どこにあるのかわかりません。実際Math.round()、j6u23では、テストでj6u16と同様に動作します。他のバージョンではテストしていません。

于 2012-07-04T12:24:26.223 に答える
5

はい; アンダーフローやオーバーフローを考慮していません。実用的に言えば、これはアプリケーションにとって重要ではないかもしれません。

于 2009-11-17T18:18:12.300 に答える