ฉันจะสร้างจำนวนเต็มแบบสุ่มภายในช่วงที่ระบุใน Java ได้อย่างไร


3503

ฉันจะสร้างintค่าสุ่มในช่วงที่ระบุได้อย่างไร

ฉันได้ลองสิ่งต่อไปนี้แล้ว แต่สิ่งเหล่านี้ใช้ไม่ได้:

ความพยายามที่ 1:

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

พยายาม 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`.

เมื่อคุณต้องการตัวเลขสุ่มจำนวนมากฉันไม่แนะนำคลาส Random ใน API มันมีระยะเวลาน้อยเกินไป ลองTwers Mersenneแทน นอกจากนี้การใช้งาน Java
raupach

1
ก่อนที่คุณจะโพสต์คำตอบใหม่พิจารณาว่ามีคำตอบสำหรับคำถามนี้ 65+ ข้อ กรุณาตรวจสอบให้แน่ใจว่าคำตอบของคุณก่อให้เกิดข้อมูลที่ไม่ใช่คำตอบที่มีอยู่
janniks

คำตอบ:


3797

ในJava 1.7 หรือใหม่กว่าวิธีมาตรฐานในการทำเช่นนี้มีดังนี้:

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

ดูJavaDoc ที่เกี่ยวข้อง วิธีการนี้มีข้อได้เปรียบที่ไม่จำเป็นต้องกำหนดค่าเริ่มต้นอย่างชัดเจนเช่นjava.util.Randomซึ่งอาจเป็นแหล่งที่มาของความสับสนและข้อผิดพลาดหากใช้อย่างไม่เหมาะสม

อย่างไรก็ตามในทางกลับกันไม่มีวิธีการตั้งค่าเมล็ดพันธุ์อย่างชัดเจนดังนั้นจึงเป็นเรื่องยากที่จะทำซ้ำผลลัพธ์ในสถานการณ์ที่มีประโยชน์เช่นการทดสอบหรือการบันทึกสถานะของเกมหรือคล้ายกัน ในสถานการณ์เหล่านั้นสามารถใช้เทคนิค pre-Java 1.7 ที่แสดงด้านล่าง

ก่อน Java 1.7วิธีมาตรฐานในการทำเช่นนี้มีดังนี้:

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

ดูJavaDoc ที่เกี่ยวข้อง ในทางปฏิบัติjava.util.Randomระดับมักจะเป็นที่นิยมในการjava.lang.Math.random ()

โดยเฉพาะอย่างยิ่งไม่จำเป็นต้องสร้างวงล้อการสร้างจำนวนเต็มแบบสุ่มเมื่อมี API ตรงไปตรงมาภายในไลบรารีมาตรฐานเพื่อให้งานสำเร็จ


43
สำหรับการโทรที่มีmaxค่าจะInteger.MAX_VALUEสามารถล้นjava.lang.IllegalArgumentExceptionได้ คุณสามารถลองด้วย: randInt(0, Integer.MAX_VALUE). นอกจากนี้หากnextInt((max-min) + 1)ส่งคืนค่าที่สูงที่สุด (ค่อนข้างหายากฉันถือว่า) จะไม่ล้นอีก (สมมติว่า min และ max เป็นค่าที่สูงพอ) จะจัดการกับสถานการณ์แบบนี้ได้อย่างไร?
Daniel

3
@MoisheLipsker ต้องเป็นที่ nextLong จะไม่ผูกมัดเป็น nextInteger
mmm

13
@leventov ThreadLocalRandomถูกเพิ่มใน Java 2 1/2 ปีหลังจากคำถามนี้ถูกถามครั้งแรก ฉันมักจะมีความเห็นที่มั่นคงว่าการจัดการอินสแตนซ์แบบสุ่มอยู่นอกขอบเขตของคำถาม
Greg Case

6
ใน Android แรนด์สุ่ม = ใหม่สุ่ม ();
Webserveis

5
@Webserveis นี่คือการแก้ไขในความคิดเห็นในตัวอย่าง เวอร์ชั่นสั้น - คุณไม่ควร = สุ่มใหม่ () สำหรับทุกการเรียกฟังก์ชั่นหรือผลลัพธ์ของคุณจะไม่สุ่มพอสำหรับหลายกรณี
Greg Case

1422

โปรดทราบว่าวิธีการนี้มีอคติมากกว่าและมีประสิทธิภาพน้อยกว่าnextIntวิธีหนึ่งhttps://stackoverflow.com/a/738651/360211

หนึ่งรูปแบบมาตรฐานสำหรับการทำสิ่งนี้คือ:

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

Javaคณิตศาสตร์ฟังก์ชั่นห้องสมุด Math.random () สร้างค่า double [0,1)ในช่วง ขอให้สังเกตช่วงนี้ไม่รวมถึง 1

ในการรับช่วงของค่าเฉพาะก่อนคุณต้องคูณด้วยขนาดของช่วงของค่าที่คุณต้องการครอบคลุม

Math.random() * ( Max - Min )

ส่งคืนค่าในช่วง[0,Max-Min)โดยที่ 'Max-Min' ไม่รวมอยู่ด้วย

ตัวอย่างเช่นถ้าคุณต้องการ[5,10)คุณจะต้องครอบคลุมค่าจำนวนเต็มห้าค่าเพื่อให้คุณใช้

Math.random() * 5

นี่จะส่งคืนค่าในช่วง[0,5)โดยที่ 5 จะไม่รวม

ตอนนี้คุณต้องเปลี่ยนช่วงนี้เป็นช่วงที่คุณกำหนดเป้าหมาย คุณทำได้โดยการเพิ่มค่าต่ำสุด

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

[Min,Max)ตอนนี้คุณจะได้รับค่าในช่วง ทำตามตัวอย่างของเรานั่นหมายความว่า[5,10):

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

แต่นี่ยังไม่รวมMaxและคุณจะได้รับค่าสองเท่า ในการรับMaxค่าที่รวมคุณต้องเพิ่ม 1 ในพารามิเตอร์ช่วงของคุณ(Max - Min)แล้วตัดส่วนทศนิยมด้วยการชี้ไปที่ int สามารถทำได้ผ่าน:

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

และคุณมีมัน ค่าจำนวนเต็มแบบสุ่มในช่วง[Min,Max]หรือตามตัวอย่าง[5,10]:

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

82
เอกสารของ Sun บอกอย่างชัดเจนว่าคุณควรใช้ Random () ถ้าคุณต้องการ int แทน Math.random () ซึ่งสร้าง double ขึ้นมา
Lilian A. Moraru

6
นี่เป็นอคติจริง ๆ เมื่อเปรียบเทียบกับวิธีถัดไปของstackoverflow.com/a/738651/360211
ตะวันตก

4
"ลำเอียง" ในกรณีนี้หมายความว่าหลังจากการประหารชีวิต 2 ^ 53 ตัวเลขบางตัวจะมีการเกิดขึ้นอีกหนึ่งครั้งโดยเฉลี่ย
ปลาหมึก

378

ใช้:

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

จำนวนเต็ม x5-10ในขณะนี้คือตัวเลขสุ่มที่มีผลเป็นไปได้ของ



137

กับ พวกเขาแนะนำวิธีการints(int randomNumberOrigin, int randomNumberBound)ในRandomชั้นเรียน

ตัวอย่างเช่นถ้าคุณต้องการสร้างจำนวนเต็มห้าจำนวนสุ่ม (หรือหนึ่งเดียว) ในช่วง [0, 10] เพียงทำ:

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

พารามิเตอร์แรกระบุเพียงขนาดของการIntStreamสร้าง (ซึ่งเป็นวิธีการโอเวอร์โหลดของหนึ่งที่สร้างไม่ จำกัดIntStream)

หากคุณต้องทำการโทรหลายครั้งแยกกันคุณสามารถสร้างตัววนซ้ำดั้งเดิมแบบไม่มีที่สิ้นสุดจากสตรีม:

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

นอกจากนี้คุณยังสามารถทำได้เพื่อdoubleและlongค่า ฉันหวังว่ามันจะช่วย! :)


1
ฉันขอแนะนำให้คุณสร้างอินเทอร์เฟซตัวสุ่มให้เพียงครั้งเดียว ดูความคิดเห็นของ Greg Case เกี่ยวกับคำตอบของเขา
Naxos84

หากคุณสามารถคุณสามารถอธิบายสิ่งที่มีความสำคัญของstreamSize- พารามิเตอร์แรกของวิธีการที่ได้รับstreamSize !=0นี้ อะไรคือความแตกต่างถ้าได้รับstreamSize1/2 / n?
Erfan Ahmed

104

คุณสามารถแก้ไขตัวอย่างรหัสที่สองของคุณเป็น:

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

100

การแก้ไขครั้งแรกของคุณเพียงเล็กน้อยจะพอเพียง

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

ดูเพิ่มเติมที่นี่สำหรับการใช้งาน Random


สำหรับขั้นต่ำ <= ค่า <สูงสุดฉันก็ทำเช่นเดียวกันกับ Math: randomNum = ขั้นต่ำ + (int) (Math.random () * (สูงสุดขั้นต่ำ)); แต่การคัดเลือกนักแสดงไม่ได้ดูดีนัก)
AxelH

คำตอบซ้ำกันอย่างน้อย 7 ปี
Maarten Bodewes

70

ThreadLocalRandomเทียบเท่าของคลาสjava.util.Randomสำหรับสภาพแวดล้อมแบบมัลติเธรด การสร้างหมายเลขสุ่มจะดำเนินการแบบโลคัลในแต่ละเธรด ดังนั้นเราจึงมีประสิทธิภาพที่ดีขึ้นโดยลดความขัดแย้ง

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

x, y- ช่วงเวลาเช่น (1,10)


66

Math.Randomชั้นในJavaคือ 0-based ดังนั้นถ้าคุณเขียนอะไรแบบนี้:

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

xจะอยู่ระหว่าง0-9รวม

ดังนั้นเมื่อได้รับอาเรย์ของ25ไอเท็มต่อไปนี้โค้ดที่จะสร้างจำนวนสุ่มระหว่าง0(ฐานของอาเรย์) และarray.lengthจะเป็น:

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

index = rand.nextInt( i.length );

เนื่องจากi.lengthจะกลับมา25ที่จะกลับตัวเลขระหว่างช่วงของnextInt( i.length ) 0-24ตัวเลือกอื่นกำลังดำเนินการMath.Randomในลักษณะเดียวกัน

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

เพื่อความเข้าใจที่ดีขึ้น, ตรวจสอบการโพสต์ฟอรั่มสุ่มช่วงเวลา (archive.org)


+1 สำหรับลิงก์ภาพหน้าจอของ WayBackMachine เก็บถาวร & คำตอบของคุณยังคงมีประโยชน์อ้างอิงเพื่อรับ "สุ่ม" ints w / ในช่วง
Tapper7

มันทำให้ฉัน
งง

@CodeConfident indexตัวแปรจะไม่ส่งผลต่อผลลัพธ์ของหมายเลขสุ่ม คุณสามารถเลือกที่จะเริ่มต้นในแบบที่คุณต้องการโดยไม่ต้องกังวลกับการเปลี่ยนแปลงผลลัพธ์ หวังว่านี่จะช่วยได้
Matt R

ตรง ... มันไม่ได้ใช้อย่างสมบูรณ์ ฉันจะเริ่มต้นโดยตรงกับแรนด์:int index = rand.nextInt(i.Length);
AjahnCharles

หรือไม่เลย int index; \n index = rand...ถ้าใครชอบประกาศและการมอบหมายในบรรทัดที่แตกต่างกัน มาตรฐานการเข้ารหัสบางอย่างเข้มงวดมากขึ้น (และไม่มีจุดประสงค์ที่ชัดเจน) กว่ามาตรฐานอื่น ๆ
Mark Storer

49

ยกโทษให้ฉันสำหรับการจู้จี้จุกจิก แต่การแก้ปัญหาที่แนะนำโดยส่วนใหญ่คือmin + rng.nextInt(max - min + 1))ดูเหมือนจะเต็มไปด้วยอันตรายเนื่องจากความจริงที่ว่า:

  • rng.nextInt(n)Integer.MAX_VALUEไม่สามารถเข้าถึง
  • (max - min)อาจทำให้เกิดการล้นเมื่อminเป็นลบ

โซลูชันที่เข้าใจผิดได้จะส่งคืนผลลัพธ์ที่ถูกต้องสำหรับmin <= maxภายใน [ Integer.MIN_VALUE, Integer.MAX_VALUE] พิจารณาการนำไปปฏิบัติที่ไร้เดียงสาต่อไปนี้:

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

แม้ว่าจะไม่มีประสิทธิภาพโปรดทราบว่าความน่าจะเป็นที่จะประสบความสำเร็จในwhileลูปนั้นจะอยู่ที่ 50% หรือสูงกว่าเสมอ


ทำไมไม่โยน IllegalArgumentException เมื่อความแตกต่าง = Integer.MAX_VALUE จากนั้นคุณไม่จำเป็นต้องใช้ลูปในขณะที่
MP Korstanje

3
@mpkorstanje การติดตั้งนี้ได้รับการออกแบบมาเพื่อทำงานกับค่าใด ๆ ของ min <= max แม้ว่าความแตกต่างของพวกเขาจะเท่ากับหรือมากกว่า MAX_VALUE การวนซ้ำจนกว่าความสำเร็จจะเป็นรูปแบบทั่วไปในกรณีนี้เพื่อรับประกันการกระจายแบบสม่ำเสมอ Random.nextInt (int) ทำภายในเมื่อการโต้แย้งไม่ใช่อำนาจ 2
Christian Semrau

44

มันสามารถทำได้โดยเพียงทำคำสั่ง:

Randomizer.generate(0,10); //min of zero, max of ten

ด้านล่างเป็นรหัสที่มา

Randomizer.java

public class Randomizer {
    public static int generate(int min,int max) {
        return min + (int)(Math.random() * ((max - min) + 1));
    }
}

มันสะอาดและเรียบง่าย


5
นี่อาจเป็นการแก้ไขตัวอย่างอื่น ๆ ตอนนี้มันเป็นเพียงแค่สำเนาที่มีชื่อเสียง การชี้ให้เห็นว่า "คำตอบด้วยคะแนนโหวตมากที่สุด" นั้นยังไม่ตรงมากนักสามารถเปลี่ยนได้
Maarten Bodewes

1
นั่นคือ @MaartenBodewes ที่ถูกต้อง เมื่อฉันเขียนคำตอบนี้คำตอบที่ได้คะแนนมากที่สุดข้างต้นก็ยังเขียนเป็นวิธีแก้ปัญหาคล้ายอัลกอริทึม ตอนนี้วิธีแก้ปัญหาข้างต้นเปลี่ยนไปมากและตอนนี้คำตอบนี้ดูเหมือนแมวลอกเลียนแบบ
Abel Callejo

ฉันไม่เข้าใจว่าทำไมบิตรหัสพื้นฐานดังกล่าวไม่ได้เป็นส่วนหนึ่งของไลบรารีมาตรฐานของ Java ทำไมฉันต้องใช้สิ่งนี้
Leevi L


31

ให้เรายกตัวอย่าง

สมมติว่าฉันต้องการสร้างหมายเลขระหว่าง5-10 :

int max = 10;
int min = 5;
int diff = max - min;
Random rn = new Random();
int i = rn.nextInt(diff + 1);
i += min;
System.out.print("The Random Number is " + i);

ให้เราเข้าใจสิ่งนี้ ...

เริ่มต้นสูงสุดด้วยค่าสูงสุดและต่ำสุดด้วยค่าต่ำสุด

ตอนนี้เราจำเป็นต้องกำหนดจำนวนที่เป็นไปได้ที่จะได้รับ สำหรับตัวอย่างนี้มันจะเป็น:

5, 6, 7, 8, 9, 10

ดังนั้นจำนวนนี้จะเป็น max - min + 1

เช่น 10 - 5 + 1 = 6

ตัวเลขสุ่มจะสร้างตัวเลขระหว่าง0-5

เช่น 0, 1, 2, 3, 4, 5

การเพิ่มค่าขั้นต่ำให้กับตัวเลขสุ่มจะสร้าง:

5, 6, 7, 8, 9, 10

ดังนั้นเราจึงได้รับช่วงที่ต้องการ



26

สร้างตัวเลขสุ่มสำหรับความแตกต่างของ min และ max โดยใช้เมธอด nextint (n)จากนั้นเพิ่ม min number เข้ากับผลลัพธ์:

Random rn = new Random();
int result = rn.nextInt(max - min + 1) + min;
System.out.println(result);

26

ฉันใช้สิ่งนี้:

 /**
   * @param min - The minimum.
   * @param max - The maximum.
   * @return A random double between these numbers (inclusive the minimum and maximum).
   */
 public static double getRandom(double min, double max) {
   return (Math.random() * (max + 1 - min)) + min;
 }

คุณสามารถส่งไปที่ Integer ได้หากต้องการ


ฟังก์ชั่นนี้สร้างหมายเลขเดิมซ้ำแล้วซ้ำอีก ในกรณีของฉันมันคือ: 2147483647
sokras

ล้มเหลว: คุณมีฟังก์ชั่นที่ต้องใช้ double และทำการ +1 สิ่งนี้ขัดกับหลักการของความประหลาดใจอย่างน้อยที่สุด จะเกิดอะไรขึ้นถ้าคุณใช้ min = 0.1 และ max = 0.2
Maarten Bodewes

@ โซกราสวิธีการโทร new Random (ตรวจสอบ JavaDoc): "สร้างตัวสร้างตัวเลขสุ่มใหม่คอนสตรัคนี้จะตั้งค่าเมล็ดของตัวสร้างตัวเลขสุ่มให้เป็นค่าที่มีแนวโน้มว่าจะแตกต่างจากการเรียกใช้คอนสตรัคเตอร์นี้" มีโอกาสมากที่อาจเกี่ยวข้องกับการใช้เวลาปัจจุบันเป็นเมล็ด หากเวลานั้นใช้มิลลิวินาทีคอมพิวเตอร์ปัจจุบันจะเร็วพอที่จะสร้างหมายเลขเดียวกัน แต่นอกเหนือจากที่ 2147483647 คือInteger.MAX_VALUE; เห็นได้ชัดว่าการส่งออกขึ้นอยู่กับอินพุตซึ่งคุณไม่ได้ระบุ
Maarten Bodewes

ในที่สุดก็พบคนที่ใช้งานได้จริง
Jency

23

ในฐานะของ Java 7 Randomคุณควรจะไม่ได้ใช้ ThreadLocalRandomสำหรับการใช้งานส่วนใหญ่เครื่องกำเนิดไฟฟ้าจำนวนสุ่มของทางเลือกอยู่ในขณะนี้ สำหรับการเข้าร่วมส้อมสระว่ายน้ำและลำธารขนานใช้

SplittableRandom

Joshua Bloch Java ที่มีประสิทธิภาพ รุ่นที่สาม

เริ่มต้นจาก Java 8

สำหรับการเข้าร่วมส้อมสระว่ายน้ำและลำธารขนานการใช้งานที่มักจะได้เร็วขึ้นมีสถิติที่ดีกว่าความเป็นอิสระและความสม่ำเสมอคุณสมบัติในการเปรียบเทียบกับSplittableRandomRandom

เพื่อสร้างการสุ่มintในช่วง[0, 1_000]:

int n = new SplittableRandom().nextInt(0, 1_001);

เพื่อสร้างint[100]อาเรย์แบบสุ่มของค่าในช่วง[0, 1_000]:

int[] a = new SplittableRandom().ints(100, 0, 1_001).parallel().toArray();

วิธีคืนค่าสตรีมของค่าสุ่ม:

IntStream stream = new SplittableRandom().ints(100, 0, 1_001);

มีเหตุผลทำไมตัวอย่างรวมถึง.parallel()? ดูเหมือนว่าฉันชอบการสร้างตัวเลขสุ่ม 100 เลขอาจไม่สำคัญที่จะรับประกันความขนาน
Johnbot

@Johnbot ขอบคุณสำหรับความคิดเห็นคุณพูดถูก แต่เหตุผลหลักคือการแสดง API (แน่นอนเส้นทางสมาร์ทคือการวัดประสิทธิภาพก่อนที่จะใช้parallelการประมวลผล) อย่างไรก็ตามสำหรับอาร์เรย์ของ1_000_000องค์ประกอบparallelเวอร์ชันนั้นเร็วขึ้น 2 เท่าในเครื่องของฉันเมื่อเทียบกับลำดับ
Oleksandr Pyrohov


20

วิธีการนี้อาจใช้งานได้สะดวก:

วิธีนี้จะคืนค่าตัวเลขสุ่มระหว่างค่า min และ max ที่ให้มา:

public static int getRandomNumberBetween(int min, int max) {
    Random foo = new Random();
    int randomNumber = foo.nextInt(max - min) + min;
    if (randomNumber == min) {
        // Since the random number is between the min and max values, simply add 1
        return min + 1;
    } else {
        return randomNumber;
    }
}

และวิธีนี้จะส่งกลับตัวเลขสุ่มจากค่า min และ max ที่ให้ไว้ (ดังนั้นตัวเลขที่สร้างขึ้นอาจเป็น min หรือ max number):

public static int getRandomNumberFrom(int min, int max) {
    Random foo = new Random();
    int randomNumber = foo.nextInt((max + 1) - min) + min;

    return randomNumber;
}

// Since the random number is between the min and max values, simply add 1. ทำไม? ไม่นับขั้นต่ำใช่หรือไม่ โดยทั่วไปช่วงคือ [min, max) ซึ่ง min รวมอยู่ด้วยและ max จะถูกยกเว้น ตอบผิดโหวตลง
Maarten Bodewes

@MaartenBodewes +1 ถูกเพิ่มเนื่องจาก getRandomNumberB ระหว่างสร้างจำนวนสุ่มโดยไม่รวมจุดสิ้นสุดที่ให้ไว้
ลุคเทย์เลอร์

1
จำนวนmin + 1จะเป็นสองเท่าของแนวโน้มที่จะเป็นผลมาจากgetRandomNumberBetween!
Lii

19

ในกรณีของการทอยลูกเต๋ามันจะสุ่มหมายเลขระหว่าง 1 ถึง 6 (ไม่ใช่ 0 ถึง 6) ดังนั้น:

face = 1 + randomNumbers.nextInt(6);

19
int random = minimum + Double.valueOf(Math.random()*(maximum-minimum )).intValue();

หรือลองดูเพื่อ RandomUtils จากApache คอมมอนส์


มีประโยชน์ แต่ระวังข้อบกพร่องเล็ก ๆ : ลายเซ็นของเมธอดเป็นดังนี้: nextDouble (double startInclusive, double endInclusive) แต่ถ้าคุณดูในวิธีการนั้น endInclusive ควรเป็น endExclusive
zakmck

Double.valueOf(Math.random()*(maximum-minimun)).intValue()ค่อนข้างยุ่งเหยิง (และไม่มีประสิทธิภาพ) วิธีการที่จะบอกว่า(int)(Math.random()*(maximum-minimun))...
โฮล

การสะกดไม่ตรงกันสำหรับผลตอบแทนขั้นต่ำขั้นต่ำ + Double.valueOf (Math.random () * (สูงสุด - ขั้นต่ำ)) intValue ();
Hrishikesh Mishra

18

นี่คือคลาสที่มีประโยชน์ในการสร้างแบบสุ่มintsในช่วงที่มีการรวมกันของขอบเขตรวม / พิเศษ:

import java.util.Random;

public class RandomRange extends Random {
    public int nextIncInc(int min, int max) {
        return nextInt(max - min + 1) + min;
    }

    public int nextExcInc(int min, int max) {
        return nextInt(max - min) + 1 + min;
    }

    public int nextExcExc(int min, int max) {
        return nextInt(max - min - 1) + 1 + min;
    }

    public int nextIncExc(int min, int max) {
        return nextInt(max - min) + min;
    }
}

18

ในการสร้างตัวเลขสุ่ม "ระหว่างตัวเลขสองตัว" ให้ใช้รหัสต่อไปนี้:

Random r = new Random();
int lowerBound = 1;
int upperBound = 11;
int result = r.nextInt(upperBound-lowerBound) + lowerBound;

ซึ่งจะให้ตัวเลขสุ่มในระหว่าง 1 (รวม) และ 11 (พิเศษ) ดังนั้นเริ่มต้นค่า UpperBound โดยการเพิ่ม 1 ตัวอย่างเช่นถ้าคุณต้องการสร้างตัวเลขสุ่มระหว่าง 1 ถึง 10 จากนั้นเริ่มต้นหมายเลข UpperBound ด้วย 11 แทน 10


18

คุณสามารถบรรลุเป้าหมายดังกล่าวใน Java 8:

Random random = new Random();

int max = 10;
int min = 5;
int totalNumber = 10;

IntStream stream = random.ints(totalNumber, min, max);
stream.forEach(System.out::println);

17
public static Random RANDOM = new Random(System.nanoTime());

public static final float random(final float pMin, final float pMax) {
    return pMin + RANDOM.nextFloat() * (pMax - pMin);
}

16

อีกทางเลือกหนึ่งคือใช้Apache Commons :

import org.apache.commons.math.random.RandomData;
import org.apache.commons.math.random.RandomDataImpl;

public void method() {
    RandomData randomData = new RandomDataImpl();
    int number = randomData.nextInt(5, 10);
    // ...
 }

16

ฉันพบตัวอย่างนี้สร้างตัวเลขสุ่ม :


ตัวอย่างนี้สร้างจำนวนเต็มแบบสุ่มในช่วงที่ระบุ

import java.util.Random;

/** Generate random integers in a certain range. */
public final class RandomRange {

  public static final void main(String... aArgs){
    log("Generating random integers in the range 1..10.");

    int START = 1;
    int END = 10;
    Random random = new Random();
    for (int idx = 1; idx <= 10; ++idx){
      showRandomInteger(START, END, random);
    }

    log("Done.");
  }

  private static void showRandomInteger(int aStart, int aEnd, Random aRandom){
    if ( aStart > aEnd ) {
      throw new IllegalArgumentException("Start cannot exceed End.");
    }
    //get the range, casting to long to avoid overflow problems
    long range = (long)aEnd - (long)aStart + 1;
    // compute a fraction of the range, 0 <= frac < range
    long fraction = (long)(range * aRandom.nextDouble());
    int randomNumber =  (int)(fraction + aStart);    
    log("Generated : " + randomNumber);
  }

  private static void log(String aMessage){
    System.out.println(aMessage);
  }
} 

ตัวอย่างการรันของคลาสนี้:

Generating random integers in the range 1..10.
Generated : 9
Generated : 3
Generated : 3
Generated : 9
Generated : 4
Generated : 1
Generated : 3
Generated : 9
Generated : 10
Generated : 10
Done.

14

จะดีกว่าที่จะใช้SecureRandomมากกว่าแค่สุ่ม

public static int generateRandomInteger(int min, int max) {
    SecureRandom rand = new SecureRandom();
    rand.setSeed(new Date().getTime());
    int randomNum = rand.nextInt((max - min) + 1) + min;
    return randomNum;
}

1
นี่ไม่ใช่สิ่งที่ดีเพราะถ้ามันถูกประมวลผลใน mili วินาทีเดียวกันคุณจะได้หมายเลขเดิมคุณต้องใส่การกำหนดค่าเริ่มต้น rand และ setSeet ด้านนอกของเมธอด
maraca

คุณต้องการเมล็ดใช่ แต่ใช้ SecureRandom
grep

ฉันขอโทษ แต่คนที่ปฏิเสธคำขอเปลี่ยนแปลงนั้นไม่มีเงื่อนงำการเขียนโปรแกรม Java มันเป็นข้อเสนอแนะที่ดี แต่ก็เป็นสิ่งที่ผิดเพราะถ้าดำเนินการใน mili เดียวกันวินาทีมันจะให้ตัวเลขเดียวกันไม่ใช่แบบสุ่ม
maraca

วิธีแก้ปัญหาที่ถูกต้องนั้นไม่พบที่ใดเลยมีคนไม่มากที่รู้ว่าบล็อก initializer คงที่ ... นั่นคือสิ่งที่คุณควรใช้ในการตั้งค่าเมล็ด: 1: private static int SecureRandom rand = new SecureRandom();2: static {3: rand.setSeed(...);4:}
maraca

5
ไม่จำเป็นต้องทำการเพาะเมล็ดอย่างแน่นอนSecureRandomระบบจะทำการเพาะเมล็ด การโทรโดยตรงsetSeedเป็นสิ่งที่อันตรายมากมันอาจแทนที่เมล็ด (สุ่มจริงๆ) ด้วยวันที่ และนั่นจะไม่ส่งผลอย่างแน่นอนSecureRandomเพราะใคร ๆ ก็สามารถคาดเดาเวลาและลองใช้SecureRandomอินสแตนซ์ของตนเองกับข้อมูลนั้นได้
Maarten Bodewes

13

นี่คือตัวอย่างง่ายๆที่แสดงวิธีสร้างจำนวนสุ่มจาก[min, max]ช่วงปิดขณะที่min <= max is true

คุณสามารถนำกลับมาใช้ใหม่เป็นฟิลด์ในคลาสรูทรวมถึงมีRandom.classวิธีการทั้งหมดในที่เดียว

ตัวอย่างผลลัพธ์:

RandomUtils random = new RandomUtils();
random.nextInt(0, 0); // returns 0
random.nextInt(10, 10); // returns 10
random.nextInt(-10, 10); // returns numbers from -10 to 10 (-10, -9....9, 10)
random.nextInt(10, -10); // throws assert

แหล่งที่มา:

import junit.framework.Assert;
import java.util.Random;

public class RandomUtils extends Random {

    /**
     * @param min generated value. Can't be > then max
     * @param max generated value
     * @return values in closed range [min, max].
     */
    public int nextInt(int min, int max) {
        Assert.assertFalse("min can't be > then max; values:[" + min + ", " + max + "]", min > max);
        if (min == max) {
            return max;
        }

        return nextInt(max - min + 1) + min;
    }
}

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.