Java, random number and sololearn challenges - java

How come? I thought that "+1" is the lowest number it can generate... This is the question:
"(int) Math.random()*(65535 + 1) returns a random number between:
Between 0 and 65535. <- answer
This is a question from a sololearn challenge.

The documentation of method Math.random() says:
Returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0.
It's obvious - mathematically expressed, the generated interval is <0, 1). It means, the generated number will never reach 1.0 but maximally a number a bit below (ex. 0.99). Since you multiply it with 65535, it will never reach 65535. That's why you have to add +1.
I recommend you to use the class Random and it's method nextInt(int bound) which does:
Returns a pseudorandom, uniformly distributed int value between 0 (inclusive) and the specified value (exclusive)
Therefore:
Random random = new Random();
int integer = random.nextInt(65536); // 65535 + 1 because the number is exclusive

The way you have the code right now:
(int) Math.random()*(65535 + 1)
You will always get 0.
The Math.random() method generates a number in the range [0, 1).
Returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0.
When you multiply that number by n, it has a range of [0, n). Casting it to int truncates any decimal portion of the number, making that number 0, and anything multiplied with 0 is 0. The cast occurs first because it's a higher precedence than multiplication.
Let's add parentheses so the cast occurs after the multiplication.
(int) (Math.random()*(65535 + 1))
When you multiply the truncated number by n, it has a range of [0, n). Casting it to int after the multiplication truncates any decimal portion of the number, making the range of integers 0 through (n - 1).
If you add 1 after multiplying and casting, then the lowest number it could generate would be 1. The range before adding would be 0 through 65534, after adding it would be 1 through 65535.
(int) (Math.random()*65535) + 1

How come? I thought that "+1" is the lowest number it can generate...
That is because the +1 was placed within the brackets. See below:
(int) Math.random()*(65535 + 1) //is equivalent to
(int) Math.random()*(65536) //which is equivalent to
(int) 0.0 to number < 1.0 *(65536) //which gives you a range of..
(int) (0 * 65536) to (0.999.. * 65536) //which gives you..
(int) 0 to 65535.34464.. //converted to int gives you
0 to 65535
If you want the minimum random number to be at least 1. Add it after the random operation is done:
(int) (Math.random()*65535) + 1

Related

Can Random.nextDouble() ever return the inclusive value?

I was playing around with the Random class's nextDouble() method as shown below. I expected nextDouble() to return a pseudorandom double value on the interval [-50.0, 50.0), however, after running the loop 1 billion times the output came out to maximum: 49.99999995014588 minimum: -49.99999991024878. I ran the loop without my manipulations of the output interval, and I got maximum: 0.9999999998979311 minimum: 0.0. I find this strange, because all I have done to the 0.0 that was returned is multiply it by 100.0 and subtract 50.0 from it. Why does this code snippet below never return exactly -50.0?
EDIT: Just for fun I ran the loop another 500 million times, and the output is now: maximum: 49.99999994222232 minimum: -49.999999996750944.
import java.util.Random;
public class randomTest{
public static void main(String[] args) {
double max = 0;
double min = 0;
Random math = new Random();
for(int a = 0; a < 1000000000; a++) {
double rand = math.nextDouble() * 100.0 - (100.0 / 2.0);
max = Math.max(max, rand);
min = Math.min(min, rand);
}
System.out.println("maximum: " + max + " minimum: " + min);
}
}
The javadoc clearly states that the upper bound on nextDouble() is exclusive not inclusive. That means that 1.0 will not be returned.
According to the javadoc, 0.0 will be returned .... with a probability of approximately 1 in 254. (That is one time in 18,014,398,509,481,984.)
(It boils down to determining whether two successive calls to next(27) will return zero. That is possible, if you examine the specification for the LCNG used by next(int).)
So, your code doesn't hit 50.0 because it can't. It should be able to hit -50.0 but you would probably need to run it in the order of 1.0E19 times for that to happen. You only ran it 5.0E8 times.
nextDouble() works by first generating a random long, i.e. an integer spread evenly between the numbers -263 and 263-1. If you generate one billion numbers, you are still generating only 109/264 = 5.421 x 10-11 of the possibilities, a tiny fraction. Thus the odds that any particular number will be generated are extremely tiny.
Even accounting for rounding, the chance is still small. Note that your output contains 16 significant digits, which means that there are somewhere between 1015 and 1016 possible sequences of decimal digits you can generate. If you only generate 109 of those, the probability of generating any particular number is 10-7.
Taken from oracle docs:
public double nextDouble() Returns the next pseudorandom, uniformly
distributed double value between 0.0 and 1.0 from this random number
generator's sequence. 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.
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.
[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.]
So its clear the the max value isn't included when generating the number,
Implement it yourself. Something work for me:
public double nextDoubleInclusive()
{
return myRandom.nextInt(Integer.MAX_VALUE) / (Integer.MAX_VALUE - 1.0);
}
notice that you probably didn't get 0.0 when running without the offset.
your "min" starts with 0.0.
with a little change to your code (min = 1) you can see that you aren't getting 0.0 (you could, not the odds are against you).
double max = 0;
double min = 1;
Random math = new Random();
for(int a = 0; a < 1000000000; a++) {
double rand = math.nextDouble();
max = Math.max(max, rand);
min = Math.min(min, rand);
}
System.out.println("maximum: " + max + " minimum: " + min);
maximum: 0.9999999989149039 minimum: 4.5566594941703897E-10

Issue with saturation after calculations in Java

I'm creating a Reverse Polish Calculator and am having issues with saturation. I've implemented a stack, and have found the largest number I can get to without having the issue is 2147483647. So if I push this number to the stack, then add 1, the result I get is -2147483648 (negative). What I need to do is instead of returning this negative number, return the original number 2147483647. Basically have this as a limit. The same applies to the negative side of things, where the limit is -2147483648. Let me know if I have missed any info or you need to see code.
The largest int value is 2147483647 and the smallest is -2147483648. int values wrap around, so when you add 1 to 2147483647 you get -2147483648 and when you subtract 1 from -2147483648 you get 2147483647.
If you don't want this behaviour you can do
int a = 2147483647;
a += 1.0; // a is still 2147483647
or
int a = 2147483647;
int b = (int) (a + 1.0); // b is also 2147483647
These work because a + 1.0 is calculated using double (no overflow) and the result is converted back to an int using the rule that numbers bigger than Integer.MAX_VALUE just become Integer.MAX_VALUE.

Implementation of java.util.Random.nextInt

This function is from java.util.Random. It returns a pseudorandom int uniformly distributed between 0 and the given n. Unfortunately I did not get it.
public int nextInt(int n) {
if (n <= 0)
throw new IllegalArgumentException("n must be positive");
if ((n & -n) == n) // i.e., n is a power of 2
return (int)((n * (long)next(31)) >> 31);
int bits, val;
do {
bits = next(31);
val = bits % n;
} while (bits - val + (n-1) < 0);
return val;
}
My questions are:
Why does it treat the case where n is a power of two specially ? Is it just for performance ?
Why doest it reject numbers that bits - val + (n-1) < 0 ?
It does this in order to assure an uniform distribution of values between 0 and n. You might be tempted to do something like:
int x = rand.nextInt() % n;
but this will alter the distribution of values, unless n is a divisor of 2^31, i.e. a power of 2. This is because the modulo operator would produce equivalence classes whose size is not the same.
For instance, let's suppose that nextInt() generates an integer between 0 and 6 inclusive and you want to draw 0,1 or 2. Easy, right?
int x = rand.nextInt() % 3;
No. Let's see why:
0 % 3 = 0
1 % 3 = 1
2 % 3 = 2
3 % 3 = 0
4 % 3 = 1
5 % 3 = 2
6 % 3 = 0
So you have 3 values that map on 0 and only 2 values that map on 1 and 2. You have a bias now, as 0 is more likely to be returned than 1 or 2.
As always, the javadoc documents this behaviour:
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 int values from the
stated range with perfect uniformity.
The algorithm is slightly tricky. It rejects values that would result
in an uneven distribution (due to the fact that 2^31 is not divisible
by n). The probability of a value being rejected depends on n. The
worst case is n=2^30+1, for which the probability of a reject is 1/2,
and the expected number of iterations before the loop terminates is 2.
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. In the absence of special treatment,
the correct number of low-order bits would be returned. 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. Thus, this special case
greatly increases the length of the sequence of values returned by
successive calls to this method if n is a small power of two.
The emphasis is mine.
next generates random bits.
When n is a power of 2, a random integer in that range can be generated just by generating random bits (I assume that always generating 31 and throwing some away is for reproducibility). This code path is simpler and I guess it's a more commonly used case so it's worth making a special "fast path" for this case.
When n isn't a power of 2, it throws away numbers at the "top" of the range so that the random number is evenly distributed. E.g. imagine we had n=3, and imagine we were using 3 bits rather than 31 bits. So bits is a randomly generated number between 0 and 7. How can you generate a fair random number there? Answer: if bits is 6 or 7, we throw it away and generate a new one.

Type Casting Math.random?

Had a look around the questions on this site and could not quite find the answer I was looking for about type casting the Math.random() method from double to int.
My question is, why does Math.random only return a 0 without parentheses whereas it returns random numbers when it is contained within the parentheses?
The first part of code returns 0:
int number;
number = (int) Math.random() * 10;
System.out.println("\nThe random number is " + number);
This code works however:
int number;
number = (int) (Math.random() * 10);
System.out.println("\nThe random number is " + number);
It should be noted I have seen a few different pieces of code on typecasting whereby some programmers seem to use both ways of casting.
This code:
number = (int) Math.random() * 10;
first calculates this:
(int) Math.random()
Since Math.random() returns a number from 0 up to but not including 1, if you cast it to int, it will round down to 0. Then when you multiply 10 to 0 you get 0.
Math.random() returns a number from 0 to 1. You want to cast the result of (Math.random()*10) to int, not the number you get from Math.random itself.
Numbers get rounded down. Therefore, for example, 0.3, which you can get from Math.random, gets rounded to 0. Again, you want to round the result of 0.3 times 10, which is 3. The parenthesis is important.

Java modulo operator precedence

I need some help in debugging the following java program.
import java.util.Random;
public class NextInt
{
public static void main(String[] args)
{
for(int i=0; i<20; ++i)
{
if(i>0)
System.out.print(", ");
int x = (new Random()).nextInt();
System.out.print( x % 2 + 1);
}
System.out.println("");
}
}
Will output (for example):
0, 1, 0, 1, 2, 2, 2, 0, 0, 1, 1, 1, 2, 0, 1, 1, 1, 1, 2, 1
I think the output should have been containing only ones and twos! If we think about the x % (2+1) interpretation then the output is correct. Is the modulo operator really weaker than the addition? Java tutorial says no. Or is there something else that I am missing?
this is because a negative number % 2 = -1 and then +1 results in 0.
;)
Note that
Random.nextInt()
may produce negative ints and that, in Java, the result of the remainder operator ('%') takes the sign of the left-hand operand. This differs amongst programming languages - see this table in the Wikipedia entry for Modulo for a sampling.
If you wanted just non-negative ints, use:
Random.nextInt(Integer.MAX_VALUE)
to produce ints between 0 (inclusive) and 2^31-1 (exclusive). Otherwise, if you wanted to handle the possible negative result of modulo and still get back just 1's or 2's, then use:
System.out.print(Math.abs(x % 2) + 1);
===
JavaDoc for Random.nextInt (emphasis is mine):
public int nextInt() Returns the next pseudorandom, uniformly
distributed int value from this random number generator's sequence.
The general contract of nextInt is that one int value is
pseudorandomly generated and returned. All 2^32 possible int values
are produced with (approximately) equal probability.
public int nextInt(int n) Returns a pseudorandom, uniformly
distributed int value between 0 (inclusive) and the specified value
(exclusive), drawn from this random number generator's sequence.
===
Java Language Spec regarding the sign of the result of '%'
... It follows from this rule that the result of the remainder operation can be negative only if the dividend is negative, and can be positive only if the dividend is positive. ...
Modulo-ing a positive number in Java with a negative one will returning a negative result - which is probably where you're getting behaviour you don't expect.
Perhaps you want something like:
System.out.print(Math.abs(x % 2) + 1);
This isn't precisely defined as far as mathematics go, and thus different languages will implement this in different ways - so it's something to watch out for generally. In Pascal for instance, the result will be positive (as you probably expected for this example), and in C89 at least, it's undefined and thus could do either!
Guava's IntMath class offers an always positive modulo operation:
System.out.println(IntMath.mod(x, 2) +1);

Categories