2

In java when i want to generate a gaussien value, i use directly

Random r = new Random();
r.nextGaussian(); 

but now i want to generate a value with 1/x probability instead Gauss !

in my solution, i must create a randomly values but these values begin by the the closer to 1 and and so on (ordred). example :

0.98
0.90
0.85
0.6
0.4
...

and not

0.3
0.9
0.4
0.8
...

We have a solution on java ?

Mehdi
  • 2,160
  • 6
  • 36
  • 53
  • 2
    By '1/x', do you mean uniform probability? – pablochan Apr 30 '12 at 12:34
  • i'm sorry pablochan but i don't knwo what do you mean by uniform probability, i just want to generate randomly a several values, and a set of these values generated give a same graph like 1/x ! – Mehdi Apr 30 '12 at 12:39
  • 7
    That's impossible! The area under 1/x is infinite. – huon Apr 30 '12 at 12:40
  • If your numbers are truly random, surely there is a (random) chance that they might not even give you the distribution you expect. – James Webster Apr 30 '12 at 12:47
  • There is a promise on jscience.org on randomizers, but the source is hosted on java.net, which is inaccessible right now, under maintenance. Maybe you could check in a few hours and see if they have one already implemented. – HMM Apr 30 '12 at 12:50
  • http://stackoverflow.com/questions/5969447/java-random-integer-with-non-uniform-distribution – HMM Apr 30 '12 at 12:52
  • 1
    @user15992 - Are you saying that you need a random number generator such that if you repeatedly generated random numbers and plotted the histogram, the histogram would resemble the function 1/x? – mbeckish Apr 30 '12 at 12:53
  • Calling repeadetly several times r.nextGaussian() gives me quite random positive/negative numbers. I'm not sure what you need help with ... – Martinecko Apr 30 '12 at 12:55
  • @user15992 - I'm thinking that x=0 will cause problems, since 1/0 is infinity. Can you restrict you range to begin at some positive number > 0? – mbeckish Apr 30 '12 at 13:00
  • yes i can begin by number 0.9 and finish at 0.01 for example – Mehdi Apr 30 '12 at 13:03

3 Answers3

3

To find values distributed with probability of 1/x:

The integral of 1/x is ln x, and as @dbaupp pointed out, it grows without bound. In fact, the limit of ln x as x approaches 0 is infinite (negative), and the limit as it grows to positive infinity is infinite (positive).

So we'll have to limit the range of our function to some interval [min, max), where min > 0 and both are finite.

The inverse of q = ln x is x = e^q, so the quantile function is e^[(ln max - ln min)q + ln(min)], where q falls in the interval [0,1)

After a little algebra, that becomes (max/min)^q * min = (max^q)(min^(1-q))

(I'm not sure which form is more numerically stable)

So, plugging uniformly distributed values ranging from 0 to 1, such as you'd get from nextDouble, into this function will give you values with a pdf = 1/x and ranging from the given min to max:

public static double reciprocalQuantile(double q, double min, double max) {
    return Math.pow(max, q)*Math.pow(min, 1-q);
}

So you could say:

Random rand = new Random();
double value = reciprocalQuantile(rand.nextDouble(), 0.0001, 10000);

I think :-) Please feel free to check my math.

One more point: You could of course set min to Double.MIN_VALUE and max to Double.MAX_VALUE, but I don't know enough about floating point representations to know if that would be problematic, and if it is then I don't know how small/large a number would need to be to become so. It might also not be very useful. A little testing showed a lot of very tiny values and a lot of very large ones --- which isn't surprising, since the integrals of the top and the bottom approach infinity. So to get enough values in the middlish range for a pretty histogram, you'd need a lot of values.

maybeWeCouldStealAVan
  • 15,492
  • 2
  • 23
  • 32
0

You might need to implement your own transformation method. From Random instance, you get object for getting numbers with uniform probability and you use these as input into your method to transform it into whatever distribution you like. So you would take generated number, and use it for computation of 1/x (not sure what you mean by that ..) and return result of that operation as you need ...

Martinecko
  • 1,719
  • 4
  • 22
  • 35
-1
Random random = new SecureRandom();
double x = random.nextDouble();
return 1.0 / x; 

will give you a value 1/x for x in the range[0.0, 1.0]

Edit - doesn't answer the OP's question, I misunderstood.

mcfinnigan
  • 11,442
  • 35
  • 28
  • SecureRamdom ?! it's new for me ! what is difference between SecureRandom and simple Ramdon ? – Mehdi Apr 30 '12 at 12:40
  • Oli - hmm. you're right, my bad - shoulda thought that through properly :P – mcfinnigan Apr 30 '12 at 12:47
  • 1
    @user15992 [SecureRandom](http://docs.oracle.com/javase/7/docs/api/java/security/SecureRandom.html) is a cryptographically strong random number generator. Its use is therefore for creating random keys for cryptography. It's usually much slower than Random, no need to use it here. – Petr Janeček Apr 30 '12 at 12:49