0

I'm trying to get random double numbers between 1.0 and 10.0 using the Random.nextDouble() as such:

double number = 1.0 + (10.0-1.0) * Random.nextDouble();

Simulating this 10,000 times I find out that the probability of 1.0 and 10.0 is lower than the rest. The only way to get these number would require Random.nextDouble() to be either 0.0 or 1.0. So essentially since Random.nextDouble() gives a random number inbetween 0.0 and 1.0 it's less likely to actually result in 0.0 or 1.0.

Is there a way to mend this I wonder? Or should I try a completely different way as a whole?

EDIT:

So the problem lied indeed with rounding the numbers off to 1 decimal after generating a random double. A very crude solution I did now instead was generate a randomIntValue between 0 and 91 and then initialise the double number = 1.0 + (randomIntValue * 0.1) as such.

This is not the cleanest option i'd say.

TH3Mitch
  • 89
  • 1
  • 1
  • 10
  • There are a ton of questions on this already. Google how to generate a random number in a range in Java. – Zarwan Sep 27 '16 at 07:24
  • Are there? Where? – Bathsheba Sep 27 '16 at 07:24
  • @Bathsheba if you Google like I said... http://stackoverflow.com/questions/15055624/generating-random-doubles-in-java http://stackoverflow.com/questions/9723765/generating-a-random-double-number-of-a-certain-range-in-java http://stackoverflow.com/questions/3680637/generate-a-random-double-in-a-range – Zarwan Sep 27 '16 at 07:28
  • 1
    The OP appears to be aware of those. I read this as more of a floating point pitfall question. – Bathsheba Sep 27 '16 at 07:29
  • nextDouble can produce 0.0 but it can't produce 1.0, all values are equally likely. Note: there is 2^48 possible values for `Random` and a sample of 10,000 is unlikely to be meaningful. – Peter Lawrey Sep 27 '16 at 07:59
  • @PeterLawrey Increasing the simulations to either 100,000 or even 10,000,000 still shows 1.0 and 10.0 giving about half of the results of all other 89 possible numbers. (ex. 1.0 = 55,523, 1.1 = 110,744) – TH3Mitch Sep 27 '16 at 08:11
  • That would happen if you round the results. say you round to one decimal place, 1.0 would be half as likely as 1.1 as 1.1 has values which round up and round down to 1.1. To get 10.0 you need 9.95 or higher. In short, nothing rounds up to 1.0 and nothing rounds down to 10.0. If you truncate the number you will find 1.0 is as likely as 1.1 but 10.0 won't appear at all. – Peter Lawrey Sep 27 '16 at 08:23

2 Answers2

1

The first point to note is that (10.0-1.0) is exactly 9.0 in IEEE754 double precision floating point.

The next point to note is that Random.nextDouble() returns a number strictly less than 1.0 but greater than or equal to 0.0. It will never draw 1.0.

So we can confidently write your expression as

1.0 + 9.0 * Random.nextDouble().

The fact that this will occasionally draw 10.0 is due to floating point imprecision (in this case an unwanted round-up to the nearest floating point number). Essentially this probability is "borrowed" from the 1.0 drawing. This will be the case even if the random number generator was perfect.

There is not a "one solution fits all" solution to floating point issues. In this case, if your application really cannot tolerate the occasional 10.0 then you could "give back" that drawing to the 1.0 case. But do check that the resulting generator has the required statistical properties.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
0

So the problem lied indeed with rounding the numbers off to 1 decimal after generating a random double. A very crude solution I did now instead was generate a randomIntValue between 0 and 91 and then initialise the double number = 1.0 + (randomIntValue * 0.1) as such.

This is not the cleanest option i'd say.

TH3Mitch
  • 89
  • 1
  • 1
  • 10