generating a positive rand number in range (0, 2^63]

V

Varun Kacholia

Please correct me if I am wrong but as per my understanding
java.util.Random.nextLong() can
return a negative number as well. I need to get a positive long only.
What would be the best way?
(Math.abs wont work since it cannot convert LONG.MIN_VALUE to a
positive long).
Suggestions?

Thanks!
 
E

Eric Sosman

Varun said:
Please correct me if I am wrong but as per my understanding
java.util.Random.nextLong() can
return a negative number as well. I need to get a positive long only.
What would be the best way?
(Math.abs wont work since it cannot convert LONG.MIN_VALUE to a
positive long).

r.nextLong() >>> 1 comes to mind. Or you could use
((long)r.next(31) << 32) + r.next(32).
 
P

Patricia Shanahan

Varun said:
Please correct me if I am wrong but as per my understanding
java.util.Random.nextLong() can
return a negative number as well. I need to get a positive long only.
What would be the best way?
(Math.abs wont work since it cannot convert LONG.MIN_VALUE to a
positive long).
Suggestions?

Thanks!

If you intend to exclude zero, and include 2^63, as indicated by the
range in the subject, it cannot be done because the largest long,
Long.MAX_VALUE, is 2^63-1.

Patricia
 
E

Eric Sosman

Varun said:
Eric Sosman wrote:



that could still result in 0. (r.nextLong() >>> 1 + 1 wont help either)



0?

I apologize; I didn't notice your subject line.

Note that a `long' cannot cover the range you've asked for;
2^63 is larger than Long.MAX_VALUE. A `double' can cover the
range, but not with 63-bit accuracy. If you really need (0,2^63]
I think you'll need to use BigInteger values. The easiest way
is probably to use r.next() twice to generate a 63-bit value
in the range [0,2^63), generate a BigInteger from that (use the
BigInteger(byte[]) constructor), and add BigInteger.ONE to the
result.
 
V

Varun Kacholia

I apologize; I didn't notice your subject line.

my bad as well. i intend it to be between (0, 2^63) (excluding 0 and
2^63).
suggestions?
Note that a `long' cannot cover the range you've asked for;
2^63 is larger than Long.MAX_VALUE. A `double' can cover the
range, but not with 63-bit accuracy. If you really need (0,2^63]
I think you'll need to use BigInteger values. The easiest way
is probably to use r.next() twice to generate a 63-bit value
in the range [0,2^63), generate a BigInteger from that (use the
BigInteger(byte[]) constructor), and add BigInteger.ONE to the
result.
 
P

Patricia Shanahan

Varun said:
I apologize; I didn't notice your subject line.

my bad as well. i intend it to be between (0, 2^63) (excluding 0 and
2^63).
suggestions?
Note that a `long' cannot cover the range you've asked for;
2^63 is larger than Long.MAX_VALUE. A `double' can cover the
range, but not with 63-bit accuracy. If you really need (0,2^63]
I think you'll need to use BigInteger values. The easiest way
is probably to use r.next() twice to generate a 63-bit value
in the range [0,2^63), generate a BigInteger from that (use the
BigInteger(byte[]) constructor), and add BigInteger.ONE to the
result.

How about:

long result;
do{
result = r.nextLong() >>> 1;
}while(result == 0)

[Based on one of Eric's earlier suggestions]

Patricia
 
J

Jussi Piitulainen

Patricia said:
Varun Kacholia wrote:
I apologize; I didn't notice your subject line. my
bad as well. i intend it to be between (0, 2^63)
(excluding 0 and 2^63).
suggestions?
Note that a `long' cannot cover the range you've asked for;
2^63 is larger than Long.MAX_VALUE. A `double' can cover the
range, but not with 63-bit accuracy. If you really need (0,2^63]
I think you'll need to use BigInteger values. The easiest way
is probably to use r.next() twice to generate a 63-bit value
in the range [0,2^63), generate a BigInteger from that (use the
BigInteger(byte[]) constructor), and add BigInteger.ONE to the
result.

How about:

long result;
do{
result = r.nextLong() >>> 1;
}while(result == 0)

[Based on one of Eric's earlier suggestions]

How about just:

long result;
do {
result = r.nextLong();
}
while (result <= 0);
 
E

Eric Sosman

Jussi said:
Patricia said:
Varun Kacholia wrote:
I apologize; I didn't notice your subject line. my

bad as well. i intend it to be between (0, 2^63)
(excluding 0 and 2^63).
suggestions?


Note that a `long' cannot cover the range you've asked for;
2^63 is larger than Long.MAX_VALUE. A `double' can cover the
range, but not with 63-bit accuracy. If you really need (0,2^63]
I think you'll need to use BigInteger values. The easiest way
is probably to use r.next() twice to generate a 63-bit value
in the range [0,2^63), generate a BigInteger from that (use the
BigInteger(byte[]) constructor), and add BigInteger.ONE to the
result.

How about:

long result;
do{
result = r.nextLong() >>> 1;
}while(result == 0)

[Based on one of Eric's earlier suggestions]


How about just:

long result;
do {
result = r.nextLong();
}
while (result <= 0);

It's a "micro-pessimization." Roughly speaking, Patricia's
code will average one nextLong() call per delivered result, while
Jussi's will average two. (Patricia accepts the nextLong() value
with probability (2^63-1)/2^63 = 1-2^(-63), while Jussi accepts
each value with probability (2^63-1)/2^64 = 0.5-2^(-64).)
 
?

=?iso-8859-1?q?Fl=E1vio_Barata?=

The range you want could be generated with this code below:

long x = 0;
long y = Math.round(Math.pow(2, 63));

long randomNumber = (long) (Math.random() * (y - x -
1)) + 1;

System.out.println(x + " " + y);
System.out.println(randomNumber);

The range is (x, y] ;-)

flávio
I apologize; I didn't notice your subject line.

my bad as well. i intend it to be between (0, 2^63) (excluding 0 and
2^63).
suggestions?
Note that a `long' cannot cover the range you've asked for;
2^63 is larger than Long.MAX_VALUE. A `double' can cover the
range, but not with 63-bit accuracy. If you really need (0,2^63]
I think you'll need to use BigInteger values. The easiest way
is probably to use r.next() twice to generate a 63-bit value
in the range [0,2^63), generate a BigInteger from that (use the
BigInteger(byte[]) constructor), and add BigInteger.ONE to the
result.
 
J

Jussi Piitulainen

Eric said:
Jussi said:
Patricia Shanahan writes: ....
How about:

long result;
do{
result = r.nextLong() >>> 1;
}while(result == 0)

[Based on one of Eric's earlier suggestions]

How about just:
long result;
do {
result = r.nextLong();
}
while (result <= 0);

It's a "micro-pessimization." Roughly speaking, Patricia's
code will average one nextLong() call per delivered result, while
Jussi's will average two. (Patricia accepts the nextLong() value
with probability (2^63-1)/2^63 = 1-2^(-63), while Jussi accepts
each value with probability (2^63-1)/2^64 = 0.5-2^(-64).)

Thanks. I didn't realize her code was _that_ efficient.

I should explain why I asked about the alternative at all. The reason
is that my version is rather obviously still uniform (all the accepted
numbers are equally probable in the underlying generator) while with
your/Patricia's version something more subtle is going on, and I get
nervous when there is something subtle going on.

Let me see. Assume we have a uniform distribution for the 2^64 bit
patterns before the shift. When we lop off the rightmost bit, we are
left with 2^63 bit patterns, each of which occurred once with 0 and
once with 1 to its right, so they are all equally probable. And we
reject both occurrences of 63 zeroes.

I think I see it now. Thanks again.
 
P

Patricia Shanahan

Flávio Barata said:
The range you want could be generated with this code below:

long x = 0;
long y = Math.round(Math.pow(2, 63));

This is a bit indirect, but equivalent to:

long y = Long.MAX_VALUE;

"If the argument is positive infinity or any value greater than or equal
to the value of Long.MAX_VALUE, the result is equal to the value of
Long.MAX_VALUE" (Math.round API documentation).
long randomNumber = (long) (Math.random() * (y - x -
1)) + 1;

There are 2^53 possible results of Math.random(), the same as the number
of possible different results from Random's nextDouble() method. The
(0,2^63) range has (2^63)-1 possible values. About one in every 1024
positive longs has probability 2^-53. The others all have probability zero.

I believe the OP wanted a uniform distribution over all the longs in the
range.

Patricia
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,008
Latest member
Rahul737

Latest Threads

Top