I have a method which is generating random integers. I don't want integers to be repeated, so I created this code -
int prevInt = 0;
private int randomInt() {
int random = (int) (Math.random() * 3);
//generate random numbers between 0 to 3 inclusive
if(random == prevInt)
return randomInt();
//if previous random number is equal to currently generated
//random number, then call this method again for a different
//random number
prevInt = random;
return random;
//else return the generated random number
}
Is the above code safe to use? At worst case scenario, can it be possible that all random integers generated by Math.random() * 3 are same?
private final Random random = new Random();
private int randomInt(final int prev, final int max) {
final int next = random.nextInt(max - 1);
if(next >= prev){
return next + 1;
}else{
return next;
}
}
This will return an int between 0 and max without the need to repeat.
public static double random()
Returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0. Returned values are chosen pseudorandomly with (approximately) uniform distribution from that range.
There are two principal means of generating random (really pseudo-random) numbers:
the Random class generates random integers, doubles, longs and so on,
in various ranges.
the static method Math.random generates doubles between 0 (inclusive)
and 1 (exclusive).
To generate random integers:
do not use Math.random (it produces doubles, not integers)
use the Random class to generate random integers between 0 and N.
To generate a series of random numbers as a unit, you need to use a single Random object - do not create a new Random object for each new random number.
Other alternatives are:
SecureRandom, a cryptographically strong subclass of Random
ThreadLocalRandom, intended for multi-threaded cases
please have a look at this post.
SO Reference 1,Reference 2
From the javadoc, Math.random() return a pseudo random and (approximately) uniform distributed number within the range.
So when you don't strict accuracy you may use it. Otherwise search for better solution.
try this trivial code and see for yourself
for (int ran = 0; ran < 10; ran++) {
int random = (int) (Math.random() * 3);
System.out.println(random);
}
Output in my case
2 2 0 2 1 0 0 0 2 1
First, I must point that your question title is not that clear. Safe can mean various thing. In this case I think you mean safety of algorithm of your code, not security nor only Math.random().
Unfortunately, your code is not algorithmically safe. Even if Math.random is safe, Your code has always positive possibility on running at any time: roughly speaking it means there are no guarantee that your code ends in finite time.
Assume you are taking random number among 4 numbers. If you are drawing random number excluding right before number, you're actually not drawing from 4 numbers: it's 3. I suggest another method:
int prevInt = -1;
private int randomInt() {
if (prevInt == -1) {
int random = (int) (Math.random() * 4);
//generate random numbers between 0 to 3 inclusive
} else if
int random = (int) (Math.random() * 3);
random = (random >= prevint) ? (random + 1) % 4 : random;
}
prevInt = random;
return random;
}
private void resetRandom() {
prevInt = -1;
//use when you want to reset information that you have 'before' result.
}
This algorithm ends within finite time. Concern about whether Math.Random() itself is dangerous or whatever will be explained by other nice guys.
Yes, it is safe but we never know what is going to happen, so we can simply multiply Math.random two times to maintain a good safety
int random = (int) (Math.random() * Math.random() * 3);
Related
Given an integer, 234, how would I use a Random object to take this number and add only one random digit to it without making it a String. So the goal in this case would be to return a number that has 4 digits, with the last one being random. So for example the next number could be 2347. Then I want to take this number and do the same thing for 5 digits, for instance 23471. I know I can multiply by 10 to increase the digit count by 1, but this would not be random. The only methods I'm aware of for the Random class are nextInt(int n) and nextDouble().
Random generator = new Random();
int gameNum = 234;
public static int UpdateGameNum(int gameNum, Random)
{
gameNum = gameNum * 10 + generator.nextInt(10) would do it.
(The second argument to + is a random number in the inclusive range 0 to 9).
If you want to support negative gameNum, then use the more complex
gameNum = (gameNum >= 0 ? 1 : -1) * (Math.abs(gameNum) * 10 + generator.nextInt(10));
which effectively strips the sign, performs the concatenation of the random number, then reintroduces it.
You don't need to pass Random instance as an argument to updateGameNum()
Just multiply getNum with 10 and add a number from (0 - 9) by picking it randomly.
Random generator = new Random();
int gameNum = 234;
public static int UpdateGameNum(int gameNum)
{
return ( gameNum *10 ) + generator.nextInt(10);
}
The following code is only producing a 0 ;-;
What am I doing wrong?
public class RockPaperSci {
public static void main(String[] args) {
//Rock 1
//Paper 2
//Scissors 3
int croll =1+(int)Math.random()*3-1;
System.out.println(croll);
}
}
Edit, Another Poster suggested something that fixed it.
int croll = 1 + (int) (Math.random() * 4 - 1);
Thanks, everyone!
You are using Math.random() which states
Returns a double value with a positive sign, greater than or
equal to 0.0 and less than 1.0.
You are casting the result to an int, which returns the integer part of the value, thus 0.
Then 1 + 0 - 1 = 0.
Consider using java.util.Random
Random rand = new Random();
System.out.println(rand.nextInt(3) + 1);
Math.random() generates double values between range - [0.0, 1.0). And then you have typecasted the result to an int:
(int)Math.random() // this will always be `0`
And then multiply by 3 is 0. So, your expression is really:
1 + 0 - 1
I guess you want to put parenthesis like this:
1 + (int)(Math.random() * 3)
Having said that, you should really use Random#nextInt(int) method if you want to generate integer values in some range. It is more efficient than using Math#random().
You can use it like this:
Random rand = new Random();
int croll = 1 + rand.nextInt(3);
See also:
Math.random() versus Random.nextInt(int)
All our mates explained you reasons of unexpected output you got.
Assuming you want generate a random croll
Consider Random for resolution
Random rand= new Random();
double croll = 1 + rand.nextInt() * 3 - 1;
System.out.println(croll);
public static double random()
Returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0. Returned values are chosen pseudorandomly with (approximately) uniform distribution from that range.
int croll =1+(int)Math.random()*3-1;
eg
int croll =1+0*-1;
System.out.println(croll); // will print always 0
The following code is only producing a 0 ;-;
What am I doing wrong?
public class RockPaperSci {
public static void main(String[] args) {
//Rock 1
//Paper 2
//Scissors 3
int croll =1+(int)Math.random()*3-1;
System.out.println(croll);
}
}
Edit, Another Poster suggested something that fixed it.
int croll = 1 + (int) (Math.random() * 4 - 1);
Thanks, everyone!
You are using Math.random() which states
Returns a double value with a positive sign, greater than or
equal to 0.0 and less than 1.0.
You are casting the result to an int, which returns the integer part of the value, thus 0.
Then 1 + 0 - 1 = 0.
Consider using java.util.Random
Random rand = new Random();
System.out.println(rand.nextInt(3) + 1);
Math.random() generates double values between range - [0.0, 1.0). And then you have typecasted the result to an int:
(int)Math.random() // this will always be `0`
And then multiply by 3 is 0. So, your expression is really:
1 + 0 - 1
I guess you want to put parenthesis like this:
1 + (int)(Math.random() * 3)
Having said that, you should really use Random#nextInt(int) method if you want to generate integer values in some range. It is more efficient than using Math#random().
You can use it like this:
Random rand = new Random();
int croll = 1 + rand.nextInt(3);
See also:
Math.random() versus Random.nextInt(int)
All our mates explained you reasons of unexpected output you got.
Assuming you want generate a random croll
Consider Random for resolution
Random rand= new Random();
double croll = 1 + rand.nextInt() * 3 - 1;
System.out.println(croll);
public static double random()
Returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0. Returned values are chosen pseudorandomly with (approximately) uniform distribution from that range.
int croll =1+(int)Math.random()*3-1;
eg
int croll =1+0*-1;
System.out.println(croll); // will print always 0
I'm trying to make a method where you choose 2 number in main and the method finds the highest value between does to numbers.
The program takes a number divides it by 2, if not possible to divide multiply by 3 and add 1, divide again and so on until reaching 1.
output: number 10
6 times
int count = 0;
while( number != 1){
count++;
if(number % 2 == 0){
number = number / 2;
}else{
number = number * 3 + 1;
}
}
return count;
This is what i have so far and i have no idea how to pick 2 number and finding the highest one in between those 2.
Use the java.util.Random for generating random values.
Random r = new Random();
int n1 = r.nextInt();
int n2 = r.nextInt();
If you put what you have in a method that takes an int as a parameter, you can call it twice, once using a java.util.Random - generated number, and again using a different random value. You can store the results of both calls as ints, and compare the two of them. Hope that helps!
int first = reduceNumber(r.nextInt());
int second = reduceNumber(r.nextInt());
Use the Random class to generate random numbers.
To know the maximum of them,
int max = Math.max(n1, n2);
I'm sorry. Those to numbers are pick by me in main. I think i have to use array.
So the output should be like this:
Using Scanner in main.
lowest limit: 2
highest limit: 10000000
the number 837799(method that finds the number) is the one that is divided
the most times: 524(code that counts how many times it has been divided) which i have..
That's how it's suppose to look like. So i don't think random is going to help.
I want to choose random numbers within a range of numbers, but with weighting towards part of that range. For example:
Choose random number between 1-10
Weight it so that 1-5 is maybe 20% more likely than 6-10
Is this possible? How would I do this?
It depends on how you want your probability distribution to look like.
For example:
Pick a random number between 1-10
If it is <= 6
Return a random number between 1-5
Else
Return a random number between 6-10
EndIf
Picks a number in 1-5 60% of the time and a number in 6-10 40% of the time.
To generate a bell curve of probabilities, roll and sum multiple dice. Then subtract the average. Re-roll if the result is negative. The more dice rolled, the more weighting.
Here's one way, wholly untested.
float sum;
do {
sum = rollThreeDice(); // returns 3 to 18, with an average is 10.5
sum -= 10.5; // Now the range is 0 to 7.5, with the lower end being more likely.
} while(sum < 0);
return sum;
Of course you can roll dice with any number of sides in order to produce the desired range. You control the frequency curve by choosing the number of dice.
Two solutions come to mind. First, run a random twice:
java.utils.Random randomGenerator = new java.utils.Random();
int random = randomGenerator.nextInt(11);
if(random <= 6) { //This is 20% more
random = randomGenerator.nextInt(5) + 1;
} else {
random = randomGenerator.nextInt(5) + 6;
}
Or if you always have a static range, you could fill an array with the numbers, adding more of the numbers you want more of and choose a random over the length of the array.
Try this:
public int weightedRandom() {
int rand = Math.floor(Math.random() * 5 + 1) // From 1 to 5
if (Math.random() >= 0.6) {
++rand;
}
return rand;
}