Normalizing A Vector

Alain Ketterlin alain at dpt-info.u-strasbg.fr
Fri Jul 30 09:46:14 EDT 2010


Lawrence D'Oliveiro <ldo at geek-central.gen.new_zealand> writes:

> Say a vector V is a tuple of 3 numbers, not all zero. You want to normalize 
> it (scale all components by the same factor) so its magnitude is 1.
>
> The usual way is something like this:
>
>     L = math.sqrt(V[0] * V[0] + V[1] * V[1] + V[2] * V[2])
>     V = (V[0] / L, V[1] / L, V[2] / L)
>
> What I don’t like is having that intermediate variable L leftover after the 
> computation.

Well, it also guarantees that the square root is computed once.

> Here’s how to do it in one step:
>
>     V = tuple \
>       ( x / math.sqrt
>                 (
>                   reduce(lambda a, b : a + b, (y * y for y in V), 0)
>                 )
>           for x in V
>       )
>
> which, incidentally, also works for vectors with dimensions other than 3.

And how many times does it call math.sqrt?

(That's actually not easy to test. Does any insider know the answer?
Does the compiler hoist the math.sqrt(...) out of the implicit loop? I
guess not, because it can't assert that reduce has no side effect.)

Your best bet is to define a function that does the normalization. Your
(local) name will disappear at the end of the call. If you want it to
work for any vector size:

def norm(V):
    L = math.sqrt( sum( [x**2 for x in V] ) )
    return [ x/L for x in V ]

If you do a lot of such computations, have a look at numpy.

-- Alain.



More information about the Python-list mailing list