2016-08-27 4 views
2

Javaで乱数ジェネレータを作成する - num1とnum2を見ると、これらのメソッドのどちらを使っても1から8までの乱数を作成できますか? 1つは他の利点、他の利点よりも効率的ですか? 0n-1Java Math.abs random対nextInt()

import java.util.*; 

public class Chpt3 { 
    public static void main(String[] args) { 
    Random rand = new Random(); 
    int num1 = Math.abs(rand.nextInt()) % 8 + 1; 
    int num2 = rand.nextInt(8) + 1; 
    System.out.println(num1); 
    System.out.println(num2); 

    } 
} 
+0

Integerを範囲[1、9]にしたいので、あなたの意図をよりよく記述しているので、rand.nextIntを使うべきです。他に分かっていない限り、より具体的な関数の内部実装は、既存の関数からそれらを構成するよりも優れている傾向があります。つまり、Javaはコンパイルされた言語であり、2つのパターンMath.abs(Math.random)とrandom.nextIntをほぼ同じ表現に正規化することによって、これらの決定の多くを無関係にする静的解析を利用します。 – Dmitry

答えて

4

Math.abs(rand.nextInt())%8 + 1;

これは微妙なバグがあります。 Math.abs(Integer.MIN_VALUE)は、負の数であるMIN_VALUEを返します。より簡単な解決策は、

(rand.nextInt() & 7) + 1; 

です。これは常に負でなく、やや速くなります。

rand.nextIntは(8)+ 1

これは、両方の高速ですが、もっと重要なのは、あなたが達成しようとしているものに関しては明確。後の理由から、スピードだけではなく、より良い選択です。

注:実際にこのようにしたい場合はabsを使用できます。しかし、これはnextIntコールほどきれいではありません。ここで

Math.abs(rand.nextInt() % 8) + 1; 
6

nextInt(n)戻ります。あなたの二つ目は、あなたが必要とする1であることを意味するので、1〜8の間で取得する

int num2 = rand.nextInt(8) + 1; 


更新:

Math.abs(Integer.MIN_VALUE)負の値を返します。 SOにthis answerによれば

Integer.MIN_VALUE is -2147483648が、32ビット 整数を含めることができる最大値は+2147483647あります。 +2147483648を32ビット整数で表現しようとすると、実際には-2147483648にロールオーバーされます。これは、符号付き整数を使用する場合、+2147483648-2147483648の2の補数の2進表現は、 と同一であるためです。ただし、+2147483648は が範囲外と見なされるため、問題はありません。

この問題に関するもう少し読書について、あなたは をチェックアウトする場合がありますWikipedia article on Two's complement.

最初の方法だけでレアコーナーケースが含まれています。だからこそ、安全な状態で2番目のものを使うほうが良いのです。

+0

同じことをしているように見える最初の選択肢ではない理由として説明を追加できますか? –

+0

@PeterLawreyが答えを更新しました。 –

+2

彼は 'Math.abs(Integer.MIN_VALUE)'が否定を返すのはバグだとは言わなかった。彼は 'Math.abs(Integer.MIN_VALUE)'が(正しく)負を返すことができるので、 'Math.abs(rand.nextInt())%8 + 1'はバグがあると言いました。 – shmosel

1

は問題です:

int num1 = Math.abs(rand.nextInt()) % 8 + 1; 

は、あなたが最初に必要になりますその後、次に「すべての2^32の可能なint型の値が(ほぼ)均等な確率で生成さ」から番号を選択することを意味しますmodで8を返します。Math.abs()を使用しているので、1つの問題は負の数を返す可能性があることです。

int num2 = rand.nextInt(8) + 1; 

ただし、このバージョンでは、あなたが何をしたい達成するために適している負の数を返さないと8

に0から両方のコードを番号を返します。しかし、コードの2行目はメモリの方が優れています。最悪の場合は、2^32という数値を覚えておく必要があります。しかし、あなたは2番目のバージョンのためにする必要はありません。もう1つは、メソッドを少なくして全体的に計算量を少なくしなければならないため、2番目の方法はずっと高速になるということです。全体的に、両方の方法が機能しますが、第2バージョンはメモリが少なくて済み、全体的に高速ですので、ベストバージョンです。