I was wondering how to have inclusive random numbers in Clojure. I came up with this:
(import java.util.Random)
(def rnd
(Random.))
(defn random-float
[min max rnd]
(+ min (* (.nextDouble rnd) (- max min))))
It seems that Java only has inclusive/exclusive random functions. According the documentation:
The general contract of nextDouble is that one double value, chosen
(approximately) uniformly from the range 0.0d (inclusive) to 1.0d
(exclusive), is pseudorandomly generated and returned.
Is there a way to have an inclusive/inclusive version of this function. I was thinking about increasing the maximum value with a tiny bit (0.0000000000000001). Not sure what is the impact if I do so.
Would this work?
(random-float 0.0 1.0000000000000001 rnd)
How important is the double precision for your case?
You could use integers for everything with clojure.core's rand-int e.g:
for a number between 0-100: (rand-int 101)
for a number between 0-1000: (rand-int 1001)
etc
I'd also note that there are other Clojure rand-style functions such as random-sample and rand ; if rand-int isn't what you're looking for, still you probably won't need to fallback to Java.
Related
I want to use math.random() in a Java program.
What is the distribution of this way of getting doubles?
This is documented in the Java SE API docs:
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.
The doc goes on to mention that it uses java.util.Random under the hood, presumably nextDouble() (although not explicitly stated).
The remarks about nonuniformity in nextDouble are as follows:
The method nextDouble is implemented by class Random as if by:
public double nextDouble() {
return (((long)next(26) << 27) + next(27))
/ (double)(1L << 53);
}
The hedge "approximately" is used in the foregoing description only because the next method is only approximately an unbiased source of independently chosen bits. If it were a perfect source of randomly chosen bits, then the algorithm shown would choose double values from the stated range with perfect uniformity.
It appears that the non-uniformity is only due to the underlying nonuniformity of next rather than a significant bias in the nextDouble algorithm itself:
[In early versions of Java, the result was incorrectly calculated as:
return (((long)next(27) << 27) + next(27))
/ (double)(1L << 54);
This might seem to be equivalent, if not better, but in fact it
introduced a large nonuniformity because of the bias in the rounding of floating-point numbers: it was three times as likely that the low-order bit of the significand would be 0 than that it would be 1! This nonuniformity probably doesn't matter much in practice, but we strive for perfection.]
Note that this draws uniformly from the interval [0,1] separated into equal steps of 2-53, which is not the same as drawing uniformly from the set of all double values whose values are between 0 and 1. This is a subtle difference: the set of all double values between 0 and 1 is itself not uniformly spaced on the number line as this image shows:
image reproduced from docs.oracle.com
How do I safely generate a random integer value in a specific range?
I know many people have asked this before, this post for example, but the method doesn't seem to be safe. Let me explain:
The 'Math' library has Math.random() which generates a random value in the range [0, 1). Using that, one can construct an algorithm like
int randomInteger = Math.floor(Math.random() * (Integer.MAX_VALUE - Integer.MIN_VALUE + 1) + Integer.MIN_VALUE)
to generate a random number between Integer.MAX_VALUE and Integer.MIN_VALUE. However, Integer.MAX_VALUE - Integer.MIN_VALUE will overflow.
The goal is not to merely generate random numbers but to generate them evenly, meaning 1 has the same probability to appear as Integer.MAX_VALUE. I know there are work-arounds to this, such as casting large values to long but then the problem again is how to generate a long integer value from Long.MIN_VALUE to Long.MAX_VALUE.
I'm also not sure about other pre-written algorithms as they can overflow too and cause the probability distribution to change. So my question is whether there is a mathematical equation that uses only integers (no casting to long anywhere) and Math.random() to generate random numbers from Integer.MIN_VALUE to Integer.MAX_VALUE. Or if anyone know any random generators that don't get overflow internally?
The 'Math' library have Math.random() which generates a random value in [0, 1) range.
So don't use Math.random() - use this:
Random r = new Random();
int i = r.nextInt();
The docs for nextInt say:
nextInt() - Returns the next pseudorandom, uniformly distributed int value from this random number generator's sequence. All 2^32 possible int values are produced with (approximately) equal probability.
It appears I misread the question slightly, and you need long not int - luckily the contract is the same.
long l = r.nextLong()
This will quite literally take two ints and jam them together to make a long.
Still better might be to use
java.security.SecureRandom which is a cryptographically strong random number generator (RNG).
Random x = new Random(1000); // code running and generate values 1000
int i = x.nextInt();
In the example Josh gives of the flawed random method that generates a positive random number with a given upper bound n, I don't understand the two of the flaws he states.
The method from the book is:
private static final Random rnd = new Random();
//Common but deeply flawed
static int random(int n) {
return Math.abs(rnd.nextInt()) % n;
}
He says that if n is a small power of 2, the sequence of random numbers that are generated will repeat itself after a short period of time. Why is this the case? The documentation for Random.nextInt() says Returns the next pseudorandom, uniformly distributed int value from this random number generator's sequence. So shouldn't it be that if n is a small integer then the sequence will repeat itself, why does this only apply to powers of 2?
Next he says that if n is not a power of 2, some numbers will be returned on average more frequently than others. Why does this occur, if Random.nextInt() generates random integers that are uniformly distributed? (He provides a code snippet which clearly demonstrates this but I don't understand why this is the case, and how this is related to n being a power of 2).
Question 1: if n is a small power of 2, the sequence of random numbers that are generated will repeat itself after a short period of time.
This is not a corollary of anything Josh is saying; rather, it is simply a known property of linear congruential generators. Wikipedia has the following to say:
A further problem of LCGs is that the lower-order bits of the generated sequence have a far shorter period than the sequence as a whole if m is set to a power of 2. In general, the n-th least significant digit in the base b representation of the output sequence, where bk = m for some integer k, repeats with at most period bn.
This is also noted in the Javadoc:
Linear congruential pseudo-random number generators such as the one implemented by this class are known to have short periods in the sequence of values of their low-order bits.
The other version of the function, Random.nextInt(int), works around this by using different bits in this case (emphasis mine):
The algorithm treats the case where n is a power of two specially: it returns the correct number of high-order bits from the underlying pseudo-random number generator.
This is a good reason to prefer Random.nextInt(int) over using Random.nextInt() and doing your own range transformation.
Question 2: Next he says that if n is not a power of 2, some numbers will be returned on average more frequently than others.
There are 232 distinct numbers that can be returned by nextInt(). If you try to put them into n buckets by using % n, and n isn't a power of 2, some buckets will have more numbers than others. This means that some outcomes will occur more frequently than others even though the original distribution was uniform.
Let's look at this using small numbers. Let's say nextInt() returned four equiprobable outcomes, 0, 1, 2 and 3. Let's see what happens if we applied % 3 to them:
0 maps to 0
1 maps to 1
2 maps to 2
3 maps to 0
As you can see, the algorithm would return 0 twice as frequently as it would return each of 1 and 2.
This does not happen when n is a power of two, since one power of two is divisible by the other. Consider n=2:
0 maps to 0
1 maps to 1
2 maps to 0
3 maps to 1
Here, 0 and 1 occur with the same frequency.
Additional resources
Here are some additional -- if only tangentially relevant -- resources related to LCGs:
Spectral tests are statistical tests used to assess the quality of LCGs. Read more here and here.
A collection of classical pseudorandom number generators with linear structures has some pretty scatterplots (the generator used in Java is called DRAND48).
There is an interesting discussion on crypto.SE about predicting values from Java's generator.
1) When n is a power of 2, rnd % n is equivalent to selecting a few lower bits of the original. Lower bits of numbers generated by the type of generators used by java are known to be "less random" than the higher bits. It's just the property of the formula used for generating the numbers.
2) Imagine, that the largest possible value, returned by random() is 10, and n = 7. Now doing n % 7 maps numbers 7, 8, 9 and 10 into 0, 1, 2, 3 respectively. Therefore, if the original number is uniformly distributed, the result will be heavily biased towards the lower numbers, because they will appear twice as often as 4, 5 and 6. In this case, this does happen regardless of whether n is a power of two or not, but, if instead of 10 we chose, say, 15 (which is 2^4-1), then any n, that is a power of two would result in a uniform distribution, because there would be no "excess" numbers left at the end of the range to cause bias, because the total number of possible values would be exactly divisible by the number of possible remainders.
I was curious to know why random_number=a+rand()%b; in C produces a random number between a and b (non-inclusive of b). But in Java this code will not work. I understand that the correct way to do this in Java is random_number=a+(Math.random()*(b-a)); but I was curious to know why there is a difference? Isn't it the same operation mathematically? I also understand that the return types are different for the random functions, but how does this difference explain the difference in output? Sorry if this seems like a trivial question but I was curious nonetheless.
The difference lies in what each random generator does.
In Java, Math.Random returns a pseudo-random number of the range 0 (inclusive) through 1 (exclusive). So it must be scaled up by b - a, the width of the range, then shifted by a, the start of the range.
In C, rand() returns numbers in the range 0 to RAND_MAX (my RAND_MAX is 32767), so %b is used to control the width of the range, and the start of the range is shifted by a.
One can, of course use java.util.Random's nextInt() or nextInt(int n) method to more exactly mimic the C scheme. nextInt() is almost exactly the same as rand() (though hopefully better distributed) while nextInt(int n) effectively subsumes the %n calculation.
In java it is nextInt()
int nextInt(int n)
This function returns random number between 0 to n
In C it is rand()
int rand(void)
This function returns an integer value between 0 and RAND_MAX.
After I imported the math class...
Math.random()
I am confused at how to make the range of the numbers. I know you can multiply, and then add/subtract, but the logic is not making sense to me, and I am also not overly sure how to make the range. Can I get some help?
If you want the range [min, max], then you can use this formula:
Math.random() * (max - min) + min
random()
Returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0.
Make your own arrangement like if you need it below 50 multiply it by 50.
If you're trying to get a range of integers from 0 to n, then look at java.util.Random nextInt(int n)
Math.random() returns a double in between 0 and 1. So, say you wanted a number between 0 and 10:
double random = Math.random()*10;
Or maybe a range from -10 to 10:
double random = (Math.random()-0.5)*20;
Notice how I did *20 instead of 10. Subtracting 0.5 would then return a value between -0.5 and 0.5, so 0.5*20 = 10 and -0.5*20 = -10.
You have to describe you problem more. Anyway, in Java, there is class which is created specifically for working with Random numbers. Which is java.util.Random. Refer java documentation for more details. It has many methods which helps you to work with random numbers in many ways.
Some of the methods are nextInt(int limit) will give a random value between zero(inclusive) and limit(exclusive). If you need real numbers, then you have nextDouble() which will give a value between 0.0 and 1.0.