Normalize a vector
Let's imagine we want to normalize a vector of three variables; that is to compute a new vector of three values, such that its size is 1. Here is our ?rst attempt; it is a procedure that takes as input a list of three values, and gives a list of three numbers:
def normalize3(v):
return [v[0]/math.sqrt(v[0]**2+v[1]**2+v[2]**2), v[1]/math.sqrt(v[0]**2+v[1]**2+v[2]**2), v[2]/math.sqrt(v[0]**2+v[1]**2+v[2]**2)]
This is correct, but it looks pretty complicated. Let's start by giving that we're recalculating the denominator three times, and instead store the variable value.
def normalize3(v):
magv = math.sqrt(v[0]**2+v[1]**2+v[2]**2)
return [v[0]/magv,v[1]/magv,v[2]/magv]
Now, we can see a repeated structure, of going through and dividing each component by magv. Also, we seem that the computation of the magnitude of a vector is a useful and understandable operation in its own right, and could probably be give in its own method. That tends to this procedure:
def mag(v):
return math.sqrt(sum([vi**2 for vi in v]))
def normalize3(v):
return [vi/mag(v) for vi in v]
This is especially nice, because now, in fact, it gives not just to vectors of size three. So, it's both smaller and more general than what we started with. But, one of our real causes has snuck back in: we're recomputing mag(v) once for each element of the vector. So, At last, here's a version that we're very happy with:9
def mag(v):
return math.sqrt(sum([vi**2 for vi in v]))
def normalize3(v):
magv = mag(v)
return [vi/magv for vi in v]