2

I wanted to generate a uniformly random unit vector in 2 dimensions and I have been using the following snippet in C++

double ranf(double x)
{
    return double(rand()) * x / (double(RAND_MAX));
}

double phi = ranf(2 * M_PI);

double ndx = cos(phi);
double ndy = sin(phi);

Is this correct?

Akshay
  • 814
  • 6
  • 19
  • 1
    You're basically asking how to generate a floating-point number between 0 and `x`. This question probably contains your answer: http://stackoverflow.com/questions/686353/c-random-float-number-generation – djhaskin987 Jul 30 '14 at 14:31

1 Answers1

2

You're generating a random angle phi uniformly between 0 and 2Pi, which is the "heading" of your vector. By using unscaled sin and cos, you're implicitly assuming that the length of the vector is 1 and decomposing it into its vertical and horizontal components. Looks basically correct to me.

A couple of minor details: 1) When you divide by RAND_MAX rather than RAND_MAX+1, you're allowing both zero and x to occur, in your case both 0 and 2Pi, and those two values are the same in angular terms. You may want to change the divisor accordingly. 2) I'd recommend multiplying by 2.0 rather than 2 to avoid the implicit up-conversion when you multiply it by M_PI, but this is probably taken care of by your compiler anyway.

There's another way to do this which generalizes to an arbitrary number of dimensions: Generate k-tuples (z1, z2,..., zk) where each of the z's has a normal distribution. Calculate the norm N=sqrt(z12 + z22 + ... + zk2), and use it to create a normalized vector X=(z1/N, z2/N,..., zk/N). The result is that X has unit length (because of the normalization) and its direction is uniformly distributed over the k-dimensional unit hypersphere thanks to the distributional properties of the normals.

pjs
  • 18,696
  • 4
  • 27
  • 56
  • note, if `RAND_MAX` is the maximum value of its type then dividing by `RAND_MAX+1` will be problematic - be careful to write `(RAND_MAX + 1.0)` or similar – M.M Jul 30 '14 at 22:17
  • @MattMcNabb Good observation. In reality, I'd recommend avoiding `rand()` completely in favor of BOOST's `uniform_01` backed by mt19937 or one of the lagged fibonacci generators. – pjs Jul 30 '14 at 22:39