Java: do something x percent of the time - java

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....

Related

Math.random() not giving unique number; is there any issue in API?

Math.random() not working properly. Can you please help me to fix this issue?
public class MethodTest {
static Set<Long>dups=new HashSet<Long>();
public static void main(String[] args) {
while(true){
long value= (long) (Math.random() * 1000000000l);
if(dups.add(value)){
System.out.println(value);
} else{
System.out.println("Dup "+value);
break;
}
}
}
}
Random numbers aren't guaranteed to be distinct.
Think about rolling a dice: you're going to roll the same number twice if you keep rolling it repeatedly. Once you've rolled a 6-sided dice 7 times, it is impossible not to have a duplicate.
Randomness isn't about whether the value is distinct - it is the property that all values could be obtained with equal probability on each roll. If you can't roll numbers you've seen before, this decreases the probability of those numbers occurring again (to zero), whilst increasing the probability of numbers you've not seen before.
The consequence of the non-uniqueness is sometimes called the Birthday paradox - which gives the somewhat surprising result that you only need 23 people in a room before it is more likely than not that 2 people share a birthday.
According to the birthday paradox, one would expect your code to be more likely than not to have found a duplicate by (roughly) sqrt(1_000_000_000) = 10^4.5 ~= 30k iterations.
Math.random() function not guaranteed to unique value.
your program is terminated at duplicate value.
If you want unique value call the random function once again if you found duplicate value.
Some what like this.
public class Main {
static Set<Long> uniqueValues = new HashSet<Long>();
public static void main(String[] args) {
while (true) {
System.out.println("Unique Value is: "+getUniqueValue());
}
}
public static long getUniqueValue() {
boolean isUnique = false;
long value = 0;
while (!isUnique) {
value=(long) (Math.random() * 1000000000l);
isUnique = uniqueValues.add(value);
}
return value;
}
}
You will get duplicates because if you have a limited pool of numbers to choose from you will eventually end up choosing the same number twice.
Lets say you had a hat with the numbers 1 to 10 on separate pieces of paper.
You decide to choose a number. Look at it. Place it back in the hat. Then choose another number....... Keep going and the probability of choosing the same number twice before you have picked all unique numbers gets higher and higher.
You could check the number in the following line of code..
if(dups.add(value)){
System.out.println(value);
} else{
System.out.println("Dup "+value);
continue;
}
This would go to the next iteration of the loop and you would end up filling the HashSet to the brim but... you would also need to check the size of the hash set to make sure you now have all the unique numbers. So lets say you have a range of 0 - 10 then you would need to do something along the lines of...
long max = 10;
if(dups.add(value)){
System.out.println(value);
} else{
System.out.println("Dup "+value);
if (dups.size() == max) {
break;
}
continue;
}
if you want a value between a range then you have to do something along the lines of
int min = 0;
int max = 10;
int randomNum = rand.nextInt((max - min) + 1) + min;
So for your full solution you would need....
public class MethodTest {
static Set<Long>dups=new HashSet<Long>();
public static void main(String[] args) {
long value;
long min = 0;
long max = 10;
while(true) {
value = (long) rand.nextInt((max - min) + 1) + min;
if(dups.add(value)){
System.out.println(value);
} else{
System.out.println("Dup "+value);
break;
}
}
}
}
To generate a unique no first you create a list with all possible no and then suffle it.
then you can read it with iterator or other methoda as you want.

generating random numbers in java and finding percentage of how many are less than or equal to 50

My question is why isn't the code generating the amount of numbers that the users enters? Right now the code is only generating one number. Here is the original question given to me:
"In your main method, prompt the user for a number n. Write a method
called assessRandomness that generates a random number between 1 and
100 'n' times and return the percentage of times the number was less than
or equal to 50. Call your assessRandomness method from main and display
the result to the user from main. Do not interact with the user from
within the assessRandomness method."
output:
How many random numbers should I generate? 10
<assume the random numbers generated were 11 7 50 61 52 3 92 100 81 66>
40% of the numbers were 50 or less
my code:
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("how many random numbers should I generate?: ");
int number = in.nextInt();
assessRandomness(number);
}
public static double assessRandomness(int n){
int random = (int)(Math.random()*100);
int randomNumbersLessthan50 = 0;
if (random <= 50)
{
double getPercentage = random/randomNumbersLessthan50;
}
else
{
System.out.println(random);
}
return random;
}
I don't see any kind of loop within assessRandomness.
Try
for(int x = 1; x <= n; x++){ ... }
as first line in assessRandomness, it should finally look like
public static double assessRandomness(int n){
int counterLessThan50 = 0;
for ( int x = 1; x <= n; x++)
if( (int)(Math.random()*100) <= 50 ) counterLessThan50++;
return (double) counterLessThan50 / n;
}
There's no repetition in your code to do something n times.
Here's one way to do it in one line using a stream:
public static double assessRandomness(int n) {
return Stream.generate(Math::random).limit(n).map(r -> r * 100 + 1).filter(r -> r <= 50).count() / (double)n;
}
Note that converting Math.random() to a number in the range 1-100 is pointless; this will give the same result:
public static double assessRandomness(int n) {
return Stream.generate(Math::random).limit(n).filter(n -> n < .5).count() / (double)n;
}
And is easier to read.
At the moment, your assessRandomness method never uses the variable n.
At first you should initialize a variable which counts the number of created randoms that are bigger than 50 (this will be your retutn value). You should then do a loop from 0 until n. For each loop run you should create a random value between 0 and 100. Then you should check wether the value is bigger than 50. If so, count up your previously created variable. When the loop has finished, return the count variable and print it in the main method.
This should help you understand better how to do something like this.
public static void main(String[] args) {
System.out.println("how many random numbers should I generate?: ");
Scanner in = new Scanner(System.in);
int number = in.nextInt();
int[] arrayPlaceHolderInMainMethod = new int[number];
arrayPlaceHolderInMainMethod = generateRandomNumberArray(number);
assessRandomness(arrayPlaceHolderInMainMethod);
}
public static void assessRandomness(int[] inputArray) {
int randomNumbersLessthan50 = 0;
int randomNumbersGreaterthan50 = 0;
int random = 0;
for (int i = 0; i < inputArray.length; i++) {
random = inputArray[i];
}
if (random <= 50) {
randomNumbersLessthan50 += 1;
} else {
randomNumbersGreaterthan50 += 1;
}
System.out.println(">50: " + randomNumbersGreaterthan50 + " Less: " + randomNumbersLessthan50);
}
public static int[] generateRandomNumberArray(int numberPickedByUser) {
int[] arrayOfRandomNumbers = new int[numberPickedByUser];
for (int i = 0; i < numberPickedByUser; i++) {
arrayOfRandomNumbers[i] = (int) (Math.random() * 100 + 1);
}
return arrayOfRandomNumbers;
}

Different random output when run differently

I am trying to solve a problem:-
A point is at an initial position X. It can be shifted either left or right. If it is moved either left or right with equal probability 10 times, what is the probability of it ending up in its initial position X?
I used the following java program:-
import java.util.Random;
public class ProbMain {
int left;
int right;
int error;
double middle;
public ProbMain() {
left = right = error = 0;
middle = 0.0;
}
void pushLeft() {
++left;
}
void pushRight() {
++right;
}
void push() {
int whichWay;
Random rand = new Random();
whichWay = rand.nextInt(2);
if (whichWay == 0)
pushLeft();
else if (whichWay == 1)
pushRight();
else
++error;
}
public static void main(String[] args) {
ProbMain obj = new ProbMain();
for (int b = 0; b < 10000; b++) {
for (int a = 0; a < 10000; a++) {
for (int i = 0; i < 10; i++)
obj.push();
if (obj.left == obj.right)
++obj.middle;
obj.left = obj.right = 0;
}
}
System.out.println("Error: " + obj.error);
System.out.println("Probability of middle: " + obj.middle / (10000*10000));
}
}
Weird thing is that when I run this on Eclipse I get result around 0.05 but when I run from command line I get result around 0.24. Why so? And which one is correct?
You are creating a new Random object each time you want to retrieve a random number (in the push() method) - this can lead to very poor entropy and create strange results when the program is run with different timings - usually running from eclipse will be much slower due to the attached debugger, which will yield better random results when the RNG is initialized with a time value as seed.
You should change your program to use only ONE Random instance, for example by declaring a new Random member variable and initializing it once in your ProbMain constructor.

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 Random Class not truly random?

I am trying to simulate the math puzzle I found on http://blog.xkcd.com/2010/02/09/math-puzzle/. However, the java random class is returning weird results. In the code below, the result is what is expected. The output is somewhere around .612 for the first line and between .49 and .51 for the second.
int trials = 10000000;
int success = 0;
int returnstrue = 0;
for (int i = 0; i < trials; i++) {
Random r = new Random();
//double one = r.nextDouble()*10000;
//double two = r.nextDouble()*10000;
double one = 1;
double two = Math.PI;
double check = r.nextDouble();
boolean a = r.nextBoolean();
if(a)
{
returnstrue++;
}
if(a){
if((check>p(one)) && two > one)
{
success++;
}
if((check<p(one))&& two<one)
{
success++;
}
}
else{
if((check>p(two)) && two < one)
{
success++;
}
if((check<p(two))&& two>one)
{
success++;
}
}
}
System.out.println(success/(double)trials);
System.out.println(returnstrue/(double)trials);
However, when I switch the lines of
double check = r.nextDouble();
boolean a = r.nextBoolean();
to
boolean a = r.nextBoolean();
double check = r.nextDouble();
the output is around .476 for the first number and .710 for the second. This implies that the nextBoolean() method is returning true 70% of the time in the later configuration. Am I doing something wrong or is this just a bug?
Move the instantiation of r to outside the for loop, as in:
Random r = new Random();
for (int i = 0; i < trials; i++) {
:
}
What you are doing now is creating a new one every time the loop iterates and, since the seed is based on the time (milliseconds), you're likely to get quite a few with the same seed.
That's almost certainly what's skewing your results.
So, yes, it is a bug, just in your code rather than in Java. That tends to be the case in about 99.9999% of the times when people ask that question since Java itself is continuously being tested by millions around the world and that snippet of yours has been tested by, well, just you :-)

Categories

Resources