6

I've been a little curious about this. Math.random() gives a value in the range [0.0,1.0). So what might the largest value it can give be? In other words, what is the closest double value to 1.0 that is less than 1.0?

Justin
  • 24,288
  • 12
  • 92
  • 142

3 Answers3

6

Java uses 64-bit IEEE-754 representation, so the closest number smaller than one is theoretically 3FEFFFFFFFFFFFFF in hexadecimal representation, which is 0 for sign, -1 for the exponent, and 1.9999999999999997 for the 52-bit significand. This equals to roughly 0.9999999999999998.

References: IEEE-754 Calculator.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 1
    What about 0.9999999999999999? it has the same number of digits, but has a 9 instead of an 8 on the end. When I `System.out.println(0.9999999999999999 - 0.9999999999999998)`, I get: 1.1102230246251565E-16 – Justin Apr 01 '13 at 02:44
  • 1
    @gangqinlaohu The last digit is not precise. I truncated the number that I got from the IEEE-754 calculator (see the link in the answer) to get the number. The next digit after 8 is also 8, so if you apply rounding, the result becomes 0.9999999999999999. – Sergey Kalinichenko Apr 01 '13 at 02:49
  • 1
    Oh, so 0.9999999999999999 is closer than 0.9999999999999998, because 0.9999999999999998 is truncated, so the Double closest to 1 is 0.9999999999999999. – Justin Apr 01 '13 at 02:54
5

The number that you want is returned by Math.nextAfter(1.0, -1.0).

The name of the function is somewhat of a misnomer. Math.nextAfter(a, 1.0) returns the least double value that is greater than a (i.e., the next value after a), and Math.nextAfter(a, -1.0) returns the greatest value that is less than a (i.e., the value before a).

Note: Another poster said, 1.0-Double.MIN_NORMAL. That's wrong. 1.0-Double.MIN_NORMAL is exactly equal to 1.0.

Solomon Slow
  • 25,130
  • 5
  • 37
  • 57
-3

The smallest positive value of a double is Double.MIN_NORMAL. So, the largest number less than 1.0 is 1.0-Double.MIN_NORMAL.

Double.MIN_NORMAL is equal to 2-1022, so the answer is still extremely close to 1.0. You'd have to print the value of 1.0-Double.MIN_NORMAL to 308 decimal places before you could see anything but a 9.

sigpwned
  • 6,957
  • 5
  • 28
  • 48
  • 2
    Odd, when I encase `1.0 - Double.MIN_NORMAL == 1.0` in a System.out.println, I get true. But when I encase 0.9999999999999999 in the System.out.println, I get false. So does that mean that 0.9999999999999999 is the closest double to one? – Justin Apr 01 '13 at 02:41
  • Hum... Not, so, MIN_NORMAL applies to the value _closest to zero_ It is of sorts the smallest error possible on IEEE-754 values. But since you moved towards 1, some of the precision gets lost! – mjv Apr 01 '13 at 02:43
  • `System.out.println(Double.MinNormal)` gives 2.2250738585072014E-308. Pretty small. – Justin Apr 01 '13 at 02:46
  • Interesting. @dasblinkenlight is correct above and I'm wrong. Intuitively, this answer is wrong because you're "spending" your precision too low to be captured in the difference between `1.0` and `Double.MIN_NORMAL`, and so the difference is "lost." Just goes to show how confusing floating-point arithmetic is. Leaving the answer and this (non-technical) explanation for posterity. – sigpwned Apr 01 '13 at 02:51
  • Seems to me that 0.9999999999999999 is the closest number. (found it via trial and error). When I take 0.99999999999999991 - 0.9999999999999999, I get 0.0. I'm guessing that's where the digits afterwards are left off. – Justin Apr 01 '13 at 02:51