How to use Random.nextInt()? - java

I try to get random integer but i get nullpointerexception. I want to get ArrayList with first element what i add at the beggining and this is correct. Next elements i want to get three random String from answersdata[10]. I checked that in answersdata are elements what i want.
answersdata is String[]
I have error in this line:
nr1 = rand.nextInt(10);
All code of this method:
private void set_answer(int nrquestion) {
int nr1, nr2, nr3;
answers.add(answersdata[nrquestion]);
do{
nr1 = rand.nextInt(10);
}while(nr1==nrquestion);
answers.add(answersdata[nr1]);
do{
nr2 = rand.nextInt(10);
}while(nr2==nrquestion|| nr2==nr1);
answers.add(answersdata[nr2]);
do{
nr3 = rand.nextInt(10);
}while(nr3==nrquestion|| nr3==nr1 || nr3==nr2);
answers.add(answersdata[nr3]);
Collections.shuffle(answers);
}
When i write static number its working for example:
nr1 = 5;

It seems as though you forgot to initialize rand with a Random object.
Random rand = new Random(); //before trying to make calls on rand

Perhaps showing a quick method would explain how it works better than an actual explanation:
public int generateRandomNumberBetween(int min, int max){
return min + new Random().nextInt(max - min + 1);
}
The method above will generate a number between [min, max] (inclusive). It is encouraged you create a constant Random instance somewhere so you don't have to keep creating a new 1 upon each method invocation.

Related

How to generate a certain amount of random numbers within a range in Java?

I'm trying to make a small program that allows you to generate a certain amount of numbers within a range, but it does not work as expected.
For example, if I ask the program to generate 3 random numbers between 5 and 10 it gives me 5 random numbers between 0 and 5.
private void jFillActionPerformed(java.awt.event.ActionEvent evt) {
int intInput1;
int intInput2;
int intInput3;
int i;
int RandomNumber;
intInput1 = Integer.parseInt(txtInput1.getText());
intInput2 = Integer.parseInt(txtInput2.getText());
intInput3 = Integer.parseInt(txtInput3.getText());
int ListSize = (intInput3) + 1;
Random rnd = new Random();
for (i = 0; i <= ListSize; i++)
{
RandomNumber = rnd.nextInt((intInput2 - intInput1) + 1);
fill.addElement(RandomNumber);
lstNumbers.setModel(fill);
}
Simply always add 5 (or more specifically - intInput1 in your case as it seems it's lower range value) to generated numbers so it will be in the range you need (0+5=5, 5+5=10 so it will be in range 5,10)
Here an IntStream you can later than use limit to set the amount of numbers you want.
public static IntStream numbersBetween(int from, int to){
return new Random().ints().map(e -> Math.abs(e % ((to+1) - from)) + from);
}

Generate random number only one time

I have a method who randomize a number between 1 and 5.
This method needs to stop when all 5 numbers are sorted too (isn't doing it now)
My actual code is:
public ArrayList<String> generated = new ArrayList<String>(); on top
And the method itself is:
public int RandomizeQuestion () {
// Question numbers
final int min = 1;
final int max = 5;
Random r = new Random();
int qran = r.nextInt((max - min) + 1) + min;
if (Collections.singletonList(generated).contains(qran)) {
RandomizeQuestion();
} else {
generated.add(String.valueOf(qran));
}
return qran;
}
But that happens is all time the random number appears as new and this number is added repeatedly in generator array.
Collections.singletonList(generated) returns a List<ArrayList<String>> containing generated as its only element. Obviously that won't contain qran. Also, you're not checking if the list is the expected length before attempting to add a new item. Something like this should work:
if (generated.size() < max - min + 1) {
if (generated.contains(String.valueOf(qran))) {
RandomizeQuestion();
} else {
generated.add(String.valueOf(qran));
}
}
But here's a much simpler and more efficient way to shuffle a sequence of values:
// generate a list of values between min and max
generated = IntStream.rangeClosed(min, max)
.map(String::valueOf)
.collect(Collectors.toCollection(ArrayList::new));
// shuffle them
Collections.shuffle(generated);

Bug in recursive function

I'm trying to get a pin number with only 4 digits. But the numbers that are less than 1000 are also getting printed. What is happening in this code?
import java.util.Random;
public class Util {
public static int getRandomPINNumber(){
Random randomGenerator = new Random();
int randomNo = randomGenerator.nextInt(10000);
if(randomNo < 1000)
getRandomPINNumber(); //repeat if it is less than 1000,some bug here
return randomNo;
}
public static void main(String[] args){
for(int i = 0;i<100; i++)
System.out.println(getRandomPINNumber());
}
}
Output
6413
1692
5734
105 <--- why 105 is getting printed, it should reevaluate the pin right?
4857
6348
1355
The problem is that you are not returning the result of the recursive call. Change you code to:
public static int getRandomPINNumber(){
Random randomGenerator = new Random();
int randomNo = randomGenerator.nextInt(10000);
if(randomNo < 1000)
return getRandomPINNumber(); //repeat if it is less than 1000
return randomNo;
}
When you call the function for the first time and a number less than 1000 is generated, you recursively call getRandomPINNumber but ignore the return value.
Also, you should not call new Random() multiple times. Call it once and store the result.
Three things, in order of increasing pedantry
You need to return the value of the recursive function: return getRandomPINNumber(); else you're discarding the result.
Don't call Random randomGenerator = new Random(); multiple times, else you ruin the statistical properties of the generator. Have randomGenerator as a field of your class, or pass it in to your function.
Never discard results of a random number generator else you will introduce some statistical bias. (Over the years very many research papers have been debunked due to improper random number generator usage). In your case you can use int randomNo = randomGenerator.nextInt(9000) + 1000; and drop the discarding altogether.
Just a hint, actually you don't need to use recursion here:
return randomGenerator.nextInt(9000) + 1000;
is a much more simple solution.
You need to enclose the code you want to process after the if statement in curly braces and assign the result of the method to randomNo.
int randomNo = randomGenerator.nextInt(10000);
if (randomNo < 1000) {
randomNo = getRandomPINNumber(); //repeat if it is less than 1000,some bug here
}
return randomNo;
You could also avoid values that are < 1000 by using
int randomNo = randomGenerator.nextInt(9000) + 1000;
This will return numbers from 1000 to 9999 and is a much cleaner solution than recursion.
I made the code this way,
public class Util {
static Random randomGenerator = new Random();
public static int getRandomPINNumber(){
int randomNo = randomGenerator.nextInt(9000) + 1000;
return randomNo;
}
public static void main(String[] args){
for(int i = 0;i<100; i++)
System.out.println(getRandomPINNumber());
}
}
Posting the fully bug free code following all the information / tips from other answers

Java/Android Biased Number Generator

I have been set a task to create a Android app in which the user chooses four numbers (1-6), I then compare it against four randomly generated numbers and then tell them how many of there numbers were correct.
My problem is that whenever I generate any numbers the first three shown are always the same, except from the last number.
Random a1 = new Random();
random1 = new ArrayList<Integer>();
for (int index = 0; index < 6; index++)
{
random1.add(a1.nextInt(5)+ 1);
}
Random a2 = new Random();
random2 = new ArrayList<Integer>();
for (int index = 0; index < 6; index++)
{
random2.add(a2.nextInt(5)+ 1);
}
This is the code I use for the random number generation, each number uses the exact same code, which makes it even more confusing, if they were all the same I could understand that because it's the same code it generates the same number or something along those lines but the last one is always different, any help would always be appreciated.
Try not create two Random instances but reuse single instance instead. May be two Randoms with close seeds produces close output.
Check if below code works for you. Code taken from http://www.javapractices.com/topic/TopicAction.do?Id=62. Modified according to your requirements.
public final class RandomRange {
public static final void main(String... aArgs) {
int START = 1;
int END = 6;
Random random = new Random();
List<Integer> first = new ArrayList<Integer>();
List<Integer> second = new ArrayList<Integer>();
for (int idx = 1; idx <= END; ++idx) {
first.add(showRandomInteger(START, END, random));
second.add(showRandomInteger(START, END, random));
}
System.out.println(first);
System.out.println(second);
first.retainAll(second);//Find common
System.out.println(first);
}
private static int 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);
return randomNumber;
}
}

How do I generate a random n digit integer in Java using the BigInteger class?

I am unsure about how to generate a random n digit integer in Java using the BigInteger class.
private static Random rnd = new Random();
public static String getRandomNumber(int digCount) {
StringBuilder sb = new StringBuilder(digCount);
for(int i=0; i < digCount; i++)
sb.append((char)('0' + rnd.nextInt(10)));
return sb.toString();
}
And then you can use it:
new BigInteger(getRandomNumber(10000))
According to the docs, there is a constructor to do what you want in java 6: BigInteger(int, java.util.Random)
To that, you need only add a randomly selected 5000th digit-i.e. Use the rng constructor to 4999 digits, the add the last in via a separate random process. Actually, since you want to just sample performance for large values, you could generate the bits, and tack a one bit on the big end, rather than slave to decimal notation.
The simplest way would probably to be to fill a char[] array with 5000 random digits, convert that to a string, and then call the BigInteger(String) constructor.
If any of those steps gives you problems, please give more details.
Alternatively, you could do something like this:
Random rng = new Random(); // But use one instance throughout your app
BigInteger current = BigInteger.ZERO;
for (int i = 0; i < 5000; i++) {
BigInteger nextDigit = BigInteger.valueOf(rng.nextInt(10));
current = current.multiply(BigInteger.TEN).add(nextDigit);
}
I suspect that would be rather less efficient though.
You could reduce the number of steps required by generating nine random digits at a time, with rng.nextInt(1000000000).
Here are two versions, one takes a Random as parameter (in case you want to re-use it):
public static BigInteger getRandomNumber(final int digCount){
return getRandomNumber(digCount, new Random());
}
public static BigInteger getRandomNumber(final int digCount, Random rnd){
final char[] ch = new char[digCount];
for(int i = 0; i < digCount; i++){
ch[i] =
(char) ('0' + (i == 0 ? rnd.nextInt(9) + 1 : rnd.nextInt(10)));
}
return new BigInteger(new String(ch));
}
The resulting BigInteger will always have the specified length.
If n is between 1 to 12 then following method helps
private String getRandom(int length) {
if (length < 1 && length > 12) {
throw new IllegalArgumentException("Random number generator length should be between 1 to 12");
}
long nextLong = Math.abs(random.nextLong());
return String.valueOf(nextLong).substring(0, length);
}
One more thing to note is that it is not well tested code.
Take a string with 5000 digits in it then convert it into BigInteger.

Categories

Resources