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
Related
My question concerns the Java RNG; use the following code:
for (int s = 0; s < 600; s++) {
Random r = new Random(s);
System.out.println(r.nextDouble());
System.out.println(r.nextDouble() + "\n-----");
}
This will result in 600 random numbers being generated. I know this is a bit odd, but I require a new random number generator each time in my actual project. The seed I receive is sequential. The first random double that is generated is extremely close for any of the seeds, is this because of the linear congruential formula that is used as initialization?
The second double generated actually looks like it is actually properly random, is this safe to assume so? Is it OK practice to first generate an unused random number, and after that moment start to use it for the actual reason it was created?
Thank you in advance
EDIT:
Let me clarify:
int possibleRoutes = 7;
void handlePacket(Packet p) {
int chosenRoute = p.hash % possibleRoutes;
// ...Other code...
}
vs.
int possibleRoutes = 7;
void handlePacket(Packet p) {
Random r = new Random(p.hash);
int chosenRoute = r.nextInt() % possibleRoutes;
// ...Other code...
}
}
vs.
int possibleRoutes = 7;
void handlePacket(Packet p) {
Random r = new Random(p.hash);
r.nextInt();
int chosenRoute = r.nextInt() % possibleRoutes;
// ...Other code...
}
A guarantee is that each packet must take the same route. The packet hash is inherently sequential at the moment. There are too many possible hashes to keep any type of state to speed this up.
why do you give a special number as a seed? just leave it empty, so the Random constructor will choose a seed for you.
for (int s = 0; s < 600; s++) {
Random r = new Random();
System.out.println(r.nextDouble());
System.out.println(r.nextDouble() + "\n-----");
}
see Role of seed in random number generation
Call the default constructor which uses the nanoTime as a seed. This way you won't need to generate a new seed to create your object each iteration.
//loop through number of numbers needed
for(int i = 0; i < 100; i +)
//Calls default constructor
Random r = new Random();
System.out.println(r.nextDouble()*.5);
An alternative is to use a master random to seed all the subsiduary randoms in the loop:
Random masterRand = new Random();
for (int s = 0; s < 600; s++) {
Random r = new Random(masterRand.nextLong());
System.out.println(r.nextDouble());
System.out.println(r.nextDouble() + "\n-----");
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
Issue: I've completed steps 1-4 of this assignment. However, I'm currently stuck on steps 5 and 6 of this assignment, so I'm at a loss on how to combine my fizz and buzz String arrays into a separate fizzbuzz String array.
TL;DR I don't know how to do steps five and six.
Assignment:
You can do this all in the main method. This is using a game called
Fizz-Buzz, an ancient programmer’s game.
Start by initializing some variables to set the maximum and minimum value of a random number and for the capacity of an array.
(20/100)
Initialize three new arrays, one for a list of random numbers (as integers) and two for String arrays called ‘fizz’ and
‘buzz’.(20/100)
You’ll also need an integer for counting.
Write a for loop that generates a random number for each position in the array. Remember that the range for this will be set by
the two variables initialized at the beginning of the file. There are
multiple ways to create a random number, just find one that works for
you. (20/100)
Using the count of the arrays, create another array that will store all of the fizzes and buzzes without any extra space leftover in
the array. (20/100)
Use a for each loop to iterate the array and print all of the fizzes and buzzes, with no other output. (20/100)
What I've accomplished thus far:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
import java.util.Random;
/**
*
* #author
*/
public class FizzBuzz {
//2a. Initialize one int array for a list of random numbers.
private static int[] anArray;
private static final int size = 10;
//2b. Initialize two String arrays called 'fizz' and 'buzz.'
public static String[] fizz;
public static String[] buzz;
public static String[] fizzbuzz;
public static Random rand = new Random();
//1. Set the maximum and minimum value of a random number.
private static final int min = 0;
private static final int max = 5;
private static int count = 0;
public static int[] list() {
anArray = new int[size];
//3. Make an integer for counting("counter" in the for loop)
//4. Write a for loop that generates a random number for
// each position in the array.
for(count = 0; count < anArray.length; count++) {
anArray[count] = randomFill();
}
return anArray;
}
public static void print() {
for (int i = 0; i < anArray.length; i++) {
System.out.println(anArray[i] + ": " + fizz[i] + buzz[i]);
}
}
public static int randomFill() {
return rand.nextInt((max - min) + 1) + min;
}
public static String[] getF() {
fizz = new String[size];
int x = 0;
int counter;
for(counter = 0; counter < fizz.length; counter++) {
if(anArray[counter] % 3 == 0) {
fizz[counter] = "fizz";
} else {
fizz[counter] = "";
}
}
return fizz;
}
public static String[] getB() {
buzz = new String[size];
int x = 0;
int counter;
for(counter = 0; counter < buzz.length; counter++) {
if(anArray[counter] % 5 == 0) {
buzz[counter] = "buzz";
} else {
buzz[counter] = "";
}
}
return buzz;
}
public static String[] getFB() {
fizzbuzz = new String[size];
return fizzbuzz;
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
list();
getF();
getB();
print();
}
}
First of all:
How Random works
Your implementation of Random won't quite work for simple reason:
If you call the default-constructor, the seed of the PRNG will be the current time, thus you're quite likely starting multiple PRNGs with the same seed and thus receive the same random-value multiple times. Use a single Random-instance instead:
private Random rnd = new Random();
public static int randomFill() {
return rnd.nextInt((max - min) + 1) + min;
}
This should help in understanding the issue better.
General implementation
Try to stick as close to the given task as possible. E.g. the problem explicitly states that you should use a variable to specify the length of the arrays, while you're using a fixed magic-number. The task explicitly states to use two arrays fizz and buzz, you're using one array called fizzbuzz.
Inside GetFizzBuff, you probably meant x = 2; instead of x = x + 2;. Apart from that this part is fine.
Output
As above: try to stick to the given task. It's explicitly stated to only output the fizzes and buzzes, not any integers. Or at least try to print a value and the corresponding fizzes and buzzes in the same line, to produce readable output.
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.
I need a few lines of Java code that run a command x percent of the time at random.
psuedocode:
boolean x = true 10% of cases.
if(x){
System.out.println("you got lucky");
}
You just need something like this:
Random rand = new Random();
if (rand.nextInt(10) == 0) {
System.out.println("you got lucky");
}
Here's a full example that measures it:
import java.util.Random;
public class Rand10 {
public static void main(String[] args) {
Random rand = new Random();
int lucky = 0;
for (int i = 0; i < 1000000; i++) {
if (rand.nextInt(10) == 0) {
lucky++;
}
}
System.out.println(lucky); // you'll get a number close to 100000
}
}
If you want something like 34% you could use rand.nextInt(100) < 34.
If by time you mean times that the code is being executed, so that you want something, inside a code block, that is executed 10% of the times the whole block is executed you can just do something like:
Random r = new Random();
...
void yourFunction()
{
float chance = r.nextFloat();
if (chance <= 0.10f)
doSomethingLucky();
}
Of course 0.10f stands for 10% but you can adjust it. Like every PRNG algorithm this works by average usage. You won't get near to 10% unless yourFunction() is called a reasonable amount of times.
To take your code as a base, you could simply do it like that:
if(Math.random() < 0.1){
System.out.println("you got lucky");
}
FYI Math.random() uses a static instance of Random
You can use Random. You may want to seed it, but the default is often sufficient.
Random random = new Random();
int nextInt = random.nextInt(10);
if (nextInt == 0) {
// happens 10% of the time...
}
public static boolean getRandPercent(int percent) {
Random rand = new Random();
return rand.nextInt(100) <= percent;
}
You could try this:
public class MakeItXPercentOfTimes{
public boolean returnBoolean(int x){
if((int)(Math.random()*101) <= x){
return true; //Returns true x percent of times.
}
}
public static void main(String[]pps){
boolean x = returnBoolean(10); //Ten percent of times returns true.
if(x){
System.out.println("You got lucky");
}
}
}
You have to define "time" first, since 10% is a relative measure...
E.g. x is true every 5 seconds.
Or you could use a random number generator that samples uniformly from 1 to 10 and always do something if he samples a "1".
You could always generate a random number (by default it is between 0 and 1 I believe) and check if it is <= .1, again this is not uniformly random....
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.