# Vectors with a certain magnitude in Mathematica

For a user-specified magnitude, is there a way to have Mathematica produce any 3D vector with that magnitude?

• Do you want a random vector, or every vector?
– kunkelwe
Oct 12, 2012 at 0:37
• Just a random vector.
– user1676471
Oct 12, 2012 at 0:41
• Relevant math.SE question. Oct 14, 2012 at 17:02
• This is just a special case of the previous question: mathematica.stackexchange.com/questions/77131 Jun 19, 2016 at 9:37
• @Cool, this is actually much older than the question you link to, so the correct way to say it is that the latter question generalizes this one. Jul 8, 2016 at 14:07

This should work:

random3DVector[magnitude_] := magnitude * Normalize[{RandomReal[], RandomReal[], RandomReal[]}]


A 3-dimensional vector in Mathematica is just a 3-element list of the components, so we make a random 3-element list, normalize it to a unit vector, and then multiply it by the desired magnitude.

Edit: This approach is incorrect; it will only give vectors in the positive octant.

• Mr. Wizard raises a good point in another answer, that this will only produce vectors with all components positive (well, non-negative I suppose) because RandomReal[] by default produces a number between 0 and 1. So this winds up excluding 7/8 of all possible directions. Oct 14, 2012 at 5:17

If you want a random vector just because you need some arbitrary vector and you don't really care what it is, then Mr.Wizard's method of picking three random coordinates in [-1,1] will work. But if you care about the statistical properties of your vector, and in particular if you want it drawn from a uniform distribution over the surface of the sphere, then you'll have to do something a little more complicated. The reason is explained on this MathWorld page, but basically the directions of the corners of the cube have more points to pick from, so they're going to be more likely.

The same page suggests several methods of picking a vector uniformly distributed over the sphere's surface. One way would be to transform uniformly distributed random numbers $u\in[0,1],v\in[-1,1]$ into the spherical coordinate angles as

\begin{align}\theta &= 2\pi u & \phi &= \cos^{-1}v\end{align}

and then compute the components of the corresponding unit vector as

\begin{align} x &= \cos\theta\sin\phi & y &= \sin\theta\sin\phi & z &= \cos\phi \end{align}

You could wrap this up into a function as

randomVec[r_] := With[{theta=2*Pi*RandomReal[],phi=ArcCos@RandomReal[{-1,1}]},
r*{Cos[theta]Sin[phi],Sin[theta]Sin[phi],Cos[phi]}]


You may notice that $z = v$ with this method, so you could try to "optimize" the calculation by directly setting $z = v$ and calculating $\sin\phi = \sqrt{1 - z^2}$, but I don't think that's going to save much time in the computation - it's not like Mathematica is a particularly speed-optimized programming language anyway. (And it might actually make that optimization on its own, I'm not sure.)

A different method is to choose three Gaussian random numbers and normalize the resulting vector:

randomVec[r_] := r * Normalize@RandomVariate[NormalDistribution[], 3]

• I thought that seemed too easy. Thanks for finally providing the correct answer. Oct 14, 2012 at 6:39
• Muller's paper discusses the last method that David supplied. Oct 14, 2012 at 17:03
• @J.M. how about a reference that doesn't require purchase? Oct 14, 2012 at 19:55
• @Mr.Wizard you can try googling the title for pdfs out there or try accessing it from your local college/university library
– rm -rf
Oct 14, 2012 at 20:07

David's answer has given the methods for producing random points that are uniformly distributed over the surface of the sphere. Of course, there are other probability distributions on the sphere that are of interest, as well as a number of methods for generating them. For instance, here is how to generate a random unit vector which follows the von Mises-Fisher distribution, based on the proposal given here:

vonMisesFisherRandom[μ_?VectorQ, κ_?NumericQ] := Module[{ξ = RandomReal[], w},
w = 1 + (Log[ξ] + Log[1 + (1 - ξ) Exp[-2 κ]/ξ])/κ;
RotationTransform[{{0, 0, 1}, Normalize[μ]}][
Append[Sqrt[1 - w^2] Normalize[RandomVariate[NormalDistribution[], 2]], w]]]


The distribution followed by the generator given above is completely analogous to the built-in VonMisesDistribution[μ, κ]; $\mu$ here is the so-called "mean direction", and $\kappa$ is the "concentration parameter". Large values of $\kappa$ yields points that are more tightly clustered about the direction $\mu$.

This paper might also be of interest.

As a demonstration of the von Mises-Fisher distribution, here is the result of generating $10^4$ random unit vectors from this distribution, with respect to the fixed mean direction $\mu=\left(-\tfrac1{\sqrt 8}\;-\sqrt{\tfrac38}\;\frac1{\sqrt 2}\right)^\top$ and varying concentration parameter $\kappa$. Note the clustering around $\mu$ that I mentioned earlier as $\kappa$ increases. Code for the image:

With[{μ = {-1/Sqrt, -Sqrt[3/8], 1/Sqrt}},
GraphicsGrid[Partition[
Table[Graphics3D[{AbsolutePointSize,
Point[Table[vonMisesFisherRandom[μ, κ], {10^4}]]},
PlotLabel -> StringForm["κ=1", κ]],
{κ, {1/2, 1, 4, 8}}], 2]]]


As another example of a nontrivial spherical distribution, here are routines for generating a random unit vector which follows the Dimroth-Watson distribution, using the method proposed in this paper:

(* special case; κ = 0 is the uniform distribution *)
dimrothWatsonRandom[μ_?VectorQ, κ_ /; κ == 0] :=
Normalize[RandomVariate[NormalDistribution[], 3]]

dimrothWatsonRandom[μ_?VectorQ, κ_ /; NumericQ[κ] && Positive[κ]] := Module[{c, u, v, w},
c = Exp[-κ/2] Csch[κ/2]/2;
While[
{u, v} = RandomReal[1, 2]; w = Log[1 + u/c]/κ;
v > Exp[κ w (w - 1)]];
RotationTransform[{{0, 0, 1}, Normalize[μ]}][Append[
Sqrt[1 - w^2] Normalize[RandomVariate[NormalDistribution[], 2]], RandomChoice[{-1, 1}] w]]]

dimrothWatsonRandom[μ_?VectorQ, κ_ /; NumericQ[κ] && Negative[κ]] := Module[{c, d, u, v, w},
c = Sqrt[-κ]; d = ArcTan[c];
While[
{u, v} = RandomReal[1, 2]; w = Tan[d u]/c;
v > (1 - κ w^2) Exp[κ w^2]];
RotationTransform[{{0, 0, 1}, Normalize[μ]}][Append[
Sqrt[1 - w^2] Normalize[RandomVariate[NormalDistribution[], 2]], RandomChoice[{-1, 1}] w]]]


As with the von Mises-Fisher distribution, $\mu$ is a mean direction, and $\kappa$ is a concentration parameter; here, however, the clustering behavior of the variates depends on the sign of $\kappa$. For $\kappa > 0$, the Dimroth-Watson distribution is termed bipolar, with the variates clustering about the axis determined by $\mu$, while for $\kappa < 0$, the distribution is termed girdle, with the variates clustered about the great circle perpendicular to the axis determined by $\mu$.

Here is the result of generating $10^4$ random unit vectors from the Dimroth-Watson distribution, with mean direction $\mu=(0\;0\;1)^\top$ and various values of $\kappa$: RandomPoint makes this a one liner (as of version 10.2):

RandomPoint[Sphere[{0, 0, 0}, 4]]

{1.80874, 3.43311, -0.970669}


Or get multiple points at once:

RandomPoint[Sphere[{0, 0, 0}, 4], 10]

{{-2.15717, -0.871558, -3.25377}, {1.65153, 2.06714, -2.99989},
{-0.798, 3.91915, -0.0591287}, {-2.19946, 3.2677, 0.696074},
{3.21113, 2.00556, 1.29087}, {1.13529, -0.792109, 3.75282},
{3.51176, -1.82698, 0.574145}, {-1.25466, -2.03064, 3.20972},
{3.9609, 0.552069, 0.0803608}, {1.81014, 1.09316, 3.39535}}


• An even shorter one-liner would be to scale the numbers after generation: 4RandomPoint@Sphere[]. Similarly for multiple points: 4RandomPoint[Sphere[],10]. This might be less efficient for large amounts of values though. May 6, 2020 at 20:05

A very simple way to get over the corner problem is to generate random points in the cube and throw away any that are outside the sphere.

ranvec := Module[{r},
While[Norm[r = RandomReal[{-1, 1}, 3]] > 1];
Normalize[r]];

ListPointPlot3D[Table[ranvec, {30000}], PlotStyle -> PointSize[0.001],
BoxRatios -> 1, Boxed -> False, Axes -> False, ViewPoint -> Top,
ImageSize -> 250] • This is essentially Method 1 in Marsaglia's paper. Nov 2, 2012 at 1:41
• @J.M., hopefully one day I'll have a great idea that isn't 40 years too late :-) Nov 2, 2012 at 12:41
• I used this method just the other day to generate uniformly distributed random points within an ellipsoid. This method requires the least thought, but you may end up throwing away many random numbers, particularly since you have to fill the cube rather than a rectangle. Oct 11, 2013 at 17:06

I think kunkelwe's answer is on the right track but not quite there. This seems better to me:

randomVec = # * Normalize @ RandomReal[{-1, 1}, 3] &;


Test:

ListPointPlot3D[
Table[randomVec @ 5, {1500}],
BoxRatios -> 1
] David Zaslavsky shows that this too is incomplete. I shall graphically compare my incorrect result with his:

randomVecDZ = # * Normalize @ RandomReal[NormalDistribution[], 3] &;

ListPointPlot3D[Table[#@5, {30000}], PlotStyle -> PointSize[0.001],
BoxRatios -> 1, Boxed -> False, Axes -> False, ViewPoint -> Top,
ImageSize -> 250] & /@ {randomVec, randomVecDZ} // Row • Nice visualization :-) I tried to do something similar but I didn't think of shrinking the point size to make it clear. Oct 14, 2012 at 7:01
• Note the clumping of points on the left point-cloud; this shows that the distribution followed by Normalize[RandomReal[{-1, 1}, 3]] is not uniform over the surface of the sphere. Oct 14, 2012 at 17:05