Pertanyaan Bagaimana cara menghasilkan bilangan bulat acak dalam rentang tertentu di Jawa?


Bagaimana cara menghasilkan acak int nilai dalam kisaran tertentu?

Saya telah mencoba yang berikut, tetapi itu tidak berhasil:

Mencoba 1:

randomNum = minimum + (int)(Math.random() * maximum);
// Bug: `randomNum` can be bigger than `maximum`.

Mencoba 2:

Random rn = new Random();
int n = maximum - minimum + 1;
int i = rn.nextInt() % n;
randomNum =  minimum + i;
// Bug: `randomNum` can be smaller than `minimum`.

2897
2017-12-12 18:20


asal


Jawaban:


Di Java 1.7 atau lebih baru, cara standar untuk melakukan ini adalah sebagai berikut:

import java.util.concurrent.ThreadLocalRandom;

// nextInt is normally exclusive of the top value,
// so add 1 to make it inclusive
int randomNum = ThreadLocalRandom.current().nextInt(min, max + 1);

Lihat JavaDoc yang relevan. Pendekatan ini memiliki keuntungan karena tidak perlu secara eksplisit menginisialisasi java.util.Random Misalnya, yang dapat menjadi sumber kebingungan dan kesalahan jika digunakan secara tidak tepat.

Namun, sebaliknya tidak ada cara untuk secara eksplisit mengatur benih sehingga sulit untuk mereproduksi hasil dalam situasi di mana yang berguna seperti pengujian atau menyimpan status game atau yang serupa. Dalam situasi seperti itu, teknik pra-Java 1.7 yang ditunjukkan di bawah ini dapat digunakan.

Sebelum Java 1.7, cara standar untuk melakukan ini adalah sebagai berikut:

import java.util.Random;

/**
 * Returns a pseudo-random number between min and max, inclusive.
 * The difference between min and max can be at most
 * <code>Integer.MAX_VALUE - 1</code>.
 *
 * @param min Minimum value
 * @param max Maximum value.  Must be greater than min.
 * @return Integer between min and max, inclusive.
 * @see java.util.Random#nextInt(int)
 */
public static int randInt(int min, int max) {

    // NOTE: This will (intentionally) not run as written so that folks
    // copy-pasting have to think about how to initialize their
    // Random instance.  Initialization of the Random instance is outside
    // the main scope of the question, but some decent options are to have
    // a field that is initialized once and then re-used as needed or to
    // use ThreadLocalRandom (if using at least Java 1.7).
    // 
    // In particular, do NOT do 'Random rand = new Random()' here or you
    // will get not very good / not very random results.
    Random rand;

    // nextInt is normally exclusive of the top value,
    // so add 1 to make it inclusive
    int randomNum = rand.nextInt((max - min) + 1) + min;

    return randomNum;
}

Lihat JavaDoc yang relevan. Dalam prakteknya, itu java.util.Random kelas sering lebih disukai java.lang.Math.random ().

Secara khusus, tidak perlu menemukan kembali roda bilangan bulat acak ketika ada API langsung dalam pustaka standar untuk menyelesaikan tugas.


3254
2017-12-12 18:25



Perhatikan bahwa pendekatan ini lebih bias dan kurang efisien daripada a nextInt pendekatan, https://stackoverflow.com/a/738651/360211

Satu pola standar untuk mencapai ini adalah:

Min + (int)(Math.random() * ((Max - Min) + 1))

Itu Jawa Fungsi perpustakaan matematika Math.random () menghasilkan nilai ganda dalam rentang [0,1). Perhatikan rentang ini tidak termasuk 1.

Untuk mendapatkan rentang nilai tertentu terlebih dahulu, Anda perlu mengalikan dengan besarnya rentang nilai yang ingin Anda tutup.

Math.random() * ( Max - Min )

Ini mengembalikan nilai dalam rentang [0,Max-Min), di mana 'Max-Min' tidak termasuk.

Misalnya, jika Anda mau [5,10), Anda perlu mencakup lima nilai integer sehingga Anda gunakan

Math.random() * 5

Ini akan mengembalikan nilai dalam rentang [0,5), di mana 5 tidak termasuk.

Sekarang Anda perlu menggeser rentang ini ke kisaran yang Anda targetkan. Anda melakukan ini dengan menambahkan nilai Min.

Min + (Math.random() * (Max - Min))

Anda sekarang akan mendapatkan nilai dalam jangkauan [Min,Max). Mengikuti contoh kita, itu berarti [5,10):

5 + (Math.random() * (10 - 5))

Tapi, ini masih belum termasuk Max dan Anda mendapatkan nilai ganda. Untuk mendapatkan Max nilai disertakan, Anda harus menambahkan 1 ke parameter rentang Anda (Max - Min) dan kemudian memotong bagian desimal dengan mentransmisikan ke int. Ini dilakukan melalui:

Min + (int)(Math.random() * ((Max - Min) + 1))

Dan begitulah. Nilai bilangan bulat acak dalam rentang [Min,Max], atau per contoh [5,10]:

5 + (int)(Math.random() * ((10 - 5) + 1))

1323
2017-12-12 18:35



Menggunakan:

Random ran = new Random();
int x = ran.nextInt(6) + 5;

Bilangan bulat x sekarang adalah nomor acak yang memiliki kemungkinan hasil 5-10.


311
2017-09-04 04:23



Menggunakan:

minimum + rn.nextInt(maxValue - minvalue + 1)

122
2017-12-12 18:25



Dengan  mereka memperkenalkan metode ints(int randomNumberOrigin, int randomNumberBound) dalam Random kelas.

Misalnya jika Anda ingin menghasilkan lima bilangan bulat acak (atau satu pun) dalam rentang [0, 10], cukup lakukan:

Random r = new Random();
int[] fiveRandomNumbers = r.ints(5, 0, 11).toArray();
int randomNumber = r.ints(1, 0, 11).findFirst().getAsInt();

Parameter pertama menunjukkan hanya ukuran IntStream dihasilkan (yang merupakan metode kelebihan beban dari yang menghasilkan tidak terbatas IntStream).

Jika Anda perlu melakukan beberapa panggilan terpisah, Anda dapat membuat iterator primitif tak terbatas dari aliran:

public final class IntRandomNumberGenerator {

    private PrimitiveIterator.OfInt randomIterator;

    /**
     * Initialize a new random number generator that generates
     * random numbers in the range [min, max]
     * @param min - the min value (inclusive)
     * @param max - the max value (inclusive)
     */
    public IntRandomNumberGenerator(int min, int max) {
        randomIterator = new Random().ints(min, max + 1).iterator();
    }

    /**
     * Returns a random number in the range (min, max)
     * @return a random number in the range (min, max)
     */
    public int nextInt() {
        return randomIterator.nextInt();
    }
}

Anda juga dapat melakukannya untuk double dan long nilai-nilai.

Semoga itu membantu! :)


98
2017-11-26 18:29



Anda dapat mengedit contoh kode kedua Anda ke:

Random rn = new Random();
int range = maximum - minimum + 1;
int randomNum =  rn.nextInt(range) + minimum;

90
2017-12-12 18:31



Hanya modifikasi kecil dari solusi pertama Anda sudah cukup.

Random rand = new Random();
randomNum = minimum + rand.nextInt((maximum - minimum) + 1);

Lihat lebih lanjut di sini untuk implementasi Random


89
2018-03-12 22:44



ThreadLocalRandom setara dengan kelas java.util.Random untuk lingkungan multithread. Menghasilkan nomor acak dilakukan secara lokal di setiap utas. Jadi kita memiliki kinerja yang lebih baik dengan mengurangi konflik.

int rand = ThreadLocalRandom.current().nextInt(x,y);

x, y - interval mis. (1,10)


54
2018-02-12 23:19



Itu Math.Random kelas masuk Jawa adalah berbasis 0. Jadi, jika Anda menulis sesuatu seperti ini:

Random rand = new Random();
int x = rand.nextInt(10);

x akan berada di antara 0-9 inklusif.

Jadi, diberikan array berikut 25 item, kode untuk menghasilkan nomor acak antara 0 (dasar array) dan array.length akan menjadi:

String[] i = new String[25];
Random rand = new Random();
int index = 0;

index = rand.nextInt( i.length );

Sejak i.length akan kembali 25, yang nextInt( i.length ) akan mengembalikan angka di antara rentang 0-24. Pilihan lain akan terjadi Math.Random yang bekerja dengan cara yang sama.

index = (int) Math.floor(Math.random() * i.length);

Untuk pemahaman yang lebih baik, lihat posting forum Interval Acak (archive.org).


53
2018-01-08 15:04



Maafkan saya karena pemilih, tetapi solusi yang disarankan oleh mayoritas, yaitu, min + rng.nextInt(max - min + 1)), tampaknya berbahaya karena fakta bahwa:

  • rng.nextInt(n) tidak dapat dicapai Integer.MAX_VALUE.
  • (max - min) dapat menyebabkan luapan saat min negatif.

Solusi yang sangat mudah akan mengembalikan hasil yang benar untuk apa pun min <= max dalam [Integer.MIN_VALUE, Integer.MAX_VALUE]. Pertimbangkan penerapan naif berikut ini:

int nextIntInRange(int min, int max, Random rng) {
   if (min > max) {
      throw new IllegalArgumentException("Cannot draw random int from invalid range [" + min + ", " + max + "].");
   }
   int diff = max - min;
   if (diff >= 0 && diff != Integer.MAX_VALUE) {
      return (min + rng.nextInt(diff + 1));
   }
   int i;
   do {
      i = rng.nextInt();
   } while (i < min || i > max);
   return i;
}

Meskipun tidak efisien, catat bahwa probabilitas keberhasilan dalam while lingkaran akan selalu 50% atau lebih tinggi.


43
2018-01-10 13:19