Type Casting Math.random? - java

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.

Related

How do these 2 random values differ?

Is there a difference between
int number = (int) (Math.random() * 1000);
and
int number = (int)(100 + Math.random() * 900);
for generating a random 3-digit number?
Your second expression guarantees to produce a 3-digit random number but the first one does not guarantee it. The first expression can produce any integer from 0 to 999.
You can also produce a 3-digit random integer as follows:
import java.util.Random;
public class Main {
public static void main(String[] args) {
Random random = new Random();
int number = random.nextInt(900) + 100;
System.out.println(number);
}
}
Math.random() from Java API:
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.
For example:
// Generate random number
double rand = Math.random();
// Output is different everytime this code is executed
System.out.println("Random Number:" + rand);
//pseudorandom output: 0.5568515217910215
In your case:
int number = (int) (Math.random() * 1000); returns anything between 0 - 999
int number = (int)(100 + Math.random() * 900); returns anything between 100 - 999
More information from Java API
When this method is first called, it creates a single new pseudorandom-number generator, exactly as if by the expression
new java.util.Random()
This new pseudorandom-number generator is used thereafter for all calls to this method and is used nowhere else.
This method is properly synchronized to allow correct use by more than one thread. However, if many threads need to generate pseudorandom numbers at a great rate, it may reduce contention for each thread to have its own pseudorandom-number generator.
So the bottom line is:
Math.random() returns a pseudorandom double greater than or equal to 0.0 and less than 1.0.
In this kind of questions you should visit Java API instead. Hope it helped!

Java, random number and sololearn challenges

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

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

how to make Math.random round to a number

I am making a lottery type game and using Math.random() for the numbers. I want it to always print out what number you got in relation to 0 - 100 (so if Math.random outputted 0.03454 and the number to win was below 0.05, it would set the text of a label to 5). How would you make it round to just a 0.00 number?
Here is some of the code if you want to see what I mean.
public void lotterymath()
{
double x = Math.random();
System.out.println(x);
if (x <= 0.02)
output.setText("you win " + x);
else
output.setText( "you lost " + x);
}
I also have a button below that calls lotterymath() by the way :)
Edit: misread original post:
You will want to multiply by 100, and then cast to an int to truncate it, or Math.round it instead:
System.out.println(Math.round(x*100)); // rounds up or down
or
System.out.println((int) (x*100));
Original:
Use String.format(String, Object...):
System.out.println(String.format("%.2f", x));
The %.2f is a format string.
Have you tried
Math.round(x)
Checkout this link for the documentation: http://docs.oracle.com/javase/7/docs/api/java/lang/Math.html#round(double)
EDIT:
I might not have fully understanded your question, but I think if you use
Math.round(Math.random*100)
You'll get a number between 0 and 100.
I prefer to use BigDecimal when dealing with floating point numbers
BigDecimal myRounded = new BigDeicmal(Math.random()).setScale(2, BigDecimal.ROUND_HALF_UP);
Since Math.random() returns a double between 0.0 to 1.0, you can just multiply the result with 100. So 0.0 * 100 = 0, 1.0 * 100 = 100, and everything in between will always be between 0 and 100.
Use Math.round() to get a full integer number. So if the random number is 0.03454, multiplied by 100 = 3.454. Round it to get 3.
correct:
int var = (int)Math.round(Math.random()*100)
INCORRECT:
int var = Math.round(Math.random()*100)
you need to downcast to integer before assign to integer variable in order to don't get an error like this:
error: incompatible types: possible lossy conversion from long to int
int var = Math.round( Math.random() * 3);
^
When you create the variable multiply it by 100 like so:
double a = Math.random()*100;
then when you have to print it put an (int) before the variable just like down here:
System.out.print((int)a);

Why am I getting this precision error?

This is the code i am using to calculate a percentage and round it to 2 decimal places. However, at the moment, the result comes out as 45.0% rather than 45.33%
int one = 432;
int rolls = 953;
double test1 = 100 * one / rolls;
double finalValue1 = Math.round( test1 * 100.0 ) / 100.0;
Why are no decimal places showing?
as you are multiplying integers the result of test1 is integer
so you have to say
double test1= 100.0*one/rolls; or
double test1=(double)100*one/rolls
You could use String.format("%.2f",test1). If you use round, then java would round the the integer value. Thus, formatting it this way would give you the answer you seek.
The problem is with the following line:
double test1 = 100 * one / rolls;
That is because 100, one, and rolls are of type int.
When you do 100 * one, that will result in 43200. Then, we have to execute the rest of the calculation... 43200 / 953 would actually equal 45.330535152, but because these are both of type int the result will be 45. Making test1 = 45. Since test one is a double, it will actually be 45.0.
The next calculation, which uses test1 will be off because of the above, resulting in "no decimal value".
To fix this, you can change the type of one and rolls to double.
You have two problems.
First and foremost, you are performing integer division
double test1 = 100 * one / rolls;
100, one and rolls are all int. This means the result is an integer, regardless of what you've declared the return type to be. This is covered in the SO question Why the result of 1/3=0 in java?:
the result variable as double just causes an implicit conversion to occur after division.
If you want doubles, use doubles:
double one = 432.0;
double rolls = 953.0;
After fixing that, your division of Math.round( test1 * 100.0 ) / 100.0; will produce a double, but probably with more than two places of precision. It's unclear at that point if you want further rounding to a specific precision, but if you only wanted to print the two digits after the decimal you could use:
System.out.printf("%.2f", finalValue1);

Categories