Soru Java'da belirli bir aralıkta nasıl rastgele tamsayılar oluştururum?


Rastgele nasıl üretilir int Belirli bir aralıktaki değer

Aşağıdakileri denedim, ama çalışmayanlar:

Giriş 1:

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

Girişimi 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`.

2903
2017-12-12 18:20


Menşei




Cevaplar:


İçinde Java 1.7 veya üstüBunu yapmanın standart yolu şöyledir:

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);

Görmek ilgili JavaDoc. Bu yaklaşım, açık bir şekilde başlatmaya gerek duymama avantajına sahiptir. java.util.Random Örneğin, uygunsuz kullanıldığında bir karışıklık ve hata kaynağı olabilir.

Bununla birlikte, tohumun açık bir şekilde ayarlanmasının bir yolu yoktur, bu nedenle, oyun durumlarını veya benzerlerini test etme veya kaydetme gibi yararlı olduğu durumlarda sonuçları yeniden üretmenin zor olabileceği anlamına gelir. Bu durumlarda, aşağıda gösterilen Java öncesi 1.7 tekniği kullanılabilir.

Java 1.7'den önceBunu yapmanın standart yolu şöyledir:

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;
}

Görmek ilgili JavaDoc. Pratikte java.util.Random sınıf genellikle tercih edilir java.lang.Math.random ().

Özellikle, görevi tamamlamak için standart kütüphane içinde basit bir API olduğunda rastgele tamsayı nesil tekerleğini yeniden icat etmeye gerek yoktur.


3260
2017-12-12 18:25



Aramalar için max değer şudur Integer.MAX_VALUE taşması mümkündür, sonuçta java.lang.IllegalArgumentException. İle deneyebilirsiniz: randInt(0, Integer.MAX_VALUE). Ayrıca eğer nextInt((max-min) + 1) En yüksek değeri (oldukça nadir, varsayalım) tekrar taşmasına izin vermez (min ve maks değerleri varsayalım yeterince yüksek değerlerdir)? Bu tür durumlarla nasıl baş edilir? - Daniel
Bu uzun süredir çalışmıyor - momo
@MoisheLipsker GelecekLong, nextInteger olarak bir sınırlama almamalıdır - momo
@leventov ThreadLocalRandom Bu soruya ilk sorulduktan 2 ila 2 yıl sonra Java'ya eklendi. Rastgele örneğinin yönetiminin, sorunun kapsamı dışında olduğu konusunda her zaman doğru görüşteyim. - Greg Case
Android'de Rastgele rand = yeni Rastgele (); - Webserveis


Bu yaklaşımın, daha önyargılı ve daha az verimli olduğunu unutmayın. nextInt yaklaşım, https://stackoverflow.com/a/738651/360211

Bunu gerçekleştirmek için bir standart model:

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

Java Math kütüphanesi işlevi Math.random (), aralıkta bir çift değer oluşturur [0,1). Bu aralığa 1 dahil değildir.

İlk önce belirli bir değerler aralığı elde etmek için, kapsanmasını istediğiniz değer aralığının büyüklüğü ile çarpmanız gerekir.

Math.random() * ( Max - Min )

Bu aralıkta bir değer döndürür [0,Max-Min)'Max-Min' dahil değildir.

Örneğin, isterseniz [5,10)kullanmanız için beş tamsayı değerini kapsamalısınız.

Math.random() * 5

Bu aralıkta bir değer döndürür [0,5)5 dahil değildir.

Şimdi bu aralığı hedeflediğiniz aralığa kaydırmanız gerekiyor. Bunu Min değerini ekleyerek yaparsınız.

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

Şimdi aralıkta bir değer alacaksınız [Min,Max). Örneğimizi takiben, bu demektir [5,10):

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

Ancak, bu hala içermiyor Max ve çifte değer alıyorsunuz. Almak için Max değer dahil, aralık parametrenize 1 eklemeniz gerekir (Max - Min) ve daha sonra bir int'ye dönüştürerek ondalık kesiti keser. Bu üzerinden gerçekleştirilir:

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

İşte buyur. Aralıktaki rastgele bir tam sayı değeri [Min,Max]veya örnek başına [5,10]:

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

1324
2017-12-12 18:35



Sun belgeleri açıkça, Math.random () yerine bir ikili oluşturmaya gereksinim duyarsanız Random () yöntemini kullanmanız gerektiğini açıkça belirtir. - Lilian A. Moraru
Bu aslında sonraki yöntemlere göre önyargılı stackoverflow.com/a/738651/360211 - weston


kullanın:

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

Tam sayı x şimdi olası bir sonucu olan rasgele sayıdır 5-10.


311
2017-09-04 04:23





kullanın:

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

122
2017-12-12 18:25





İle  yöntemi tanıttılar ints(int randomNumberOrigin, int randomNumberBound) içinde Random sınıf.

Örneğin, [0, 10] aralığında beş rastgele tam sayı (veya bir tane) oluşturmak istiyorsanız, şunu yapın:

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

İlk parametre, yalnızca IntStream oluşturulan (sınırsız üreten birinin aşırı yüklenmiş metodu) IntStream).

Birden çok ayrı çağrı yapmanız gerekiyorsa, akıştan sonsuz bir ilkel yineleyici oluşturabilirsiniz:

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();
    }
}

İçin de yapabilirsiniz double ve long değerler.

Umarım yardımcı olur! :)


99
2017-11-26 18:29



RandomIterator'ı yalnızca bir kez başlatmanızı öneririm. Kendi yanıtına Greg Case yorum bakın. - Naxos84
eğer yapabiliyorsanız, bunun ne olduğunu açıklayabilir misiniz streamSize - verilen bu yöntemin ilk param streamSize !=0. Fark nedir streamSize 1/2 / n verilir? - Erfan Ahmed Emon
Tatlı çözüm, özellikle akış sınıfı. - cen


İkinci kod örneğinizi şu şekilde düzenleyebilirsiniz:

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

90
2017-12-12 18:31





İlk çözümünüzün sadece küçük bir değişikliği yeterli olur.

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

Uygulanması için daha fazla bakın Random


89
2018-03-12 22:44



Minimum <= değer <maksimum için, Math ile aynı şeyi yaptım: randomNum = minimum + (int) (Math.random () * (maksimum-minimum)); ama döküm görmek gerçekten güzel değil;) - AxelH


Çok iş parçacıklı ortam için sınıf java.util.Random ThreadLocalRandom eşdeğeri. Her bir dişte rastgele bir sayı üretme yerel olarak gerçekleştirilir. Bu yüzden çatışmaları azaltarak daha iyi bir performansa sahibiz.

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

x, y - aralıkları örn. (1,10)


54
2018-02-12 23:19



Allah aşkına bu cevap kabul edilmeli. Ayrıca bakınız Yazmak için herhangi bir sebep var mı new Random() Java 8'den beri mi? - leventov
@leventov bu kabul edilen cevap olamaz, bu uygulama sadece destekler => LOLLIPOP - Relm
İnsanlar bir süredir> Lollipop için geliştiriyor olmalı, bunu yapamaz, sadece pazarı sürükler. Uygulamalarınızın güncellemeye zorlamak için uygulamalarınızın daha yeni API'leri desteklemesini sağlayın. - Martin Marconcini


Math.Random sınıfta Java 0 tabanlı. Yani, böyle bir şey yazarsanız:

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

x arasında olacak 0-9 kapsayıcı.

Yani, aşağıdaki dizi göz önüne alındığında 25 öğeler arasında, rastgele bir sayı üretmek için kod 0 (dizinin tabanı) ve array.length olabilir:

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

index = rand.nextInt( i.length );

Dan beri i.length dönecek 25, nextInt( i.length ) aralığı arasında bir sayı döndürecek 0-24. Diğer seçenek ile gidiyor Math.Random Aynı şekilde çalışır.

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

Daha iyi bir anlayış için forum gönderisini kontrol edin Rastgele Aralıklar (archive.org).


53
2018-01-08 15:04



Rastgele Aralıklar bağlantısı öldü. - Tapper7
@ Tapper7 Arşivlenen bir sürüme işaret etmek için bağlantıyı güncelledi. - Matt R
WayBackMachine arşivi için +1 ekran görüntüsü linki ve cevabınız, bir aralıkta "rastgele" mürekkepleri almak için hala yararlı bir referanstır. - Tapper7
İndeksi neden 0 ile eşleştiriyorsunuz diye beni şaşırtıyor. - AjahnCharles
@CodeConfident index değişken rasgele sayının sonucunu etkilemez. Sonucu değiştirmek için endişelenmenize gerek kalmadan istediğiniz şekilde başlatabilirsiniz. Bu yardımcı olur umarım. - Matt R