My apologies if I've misunderstood the term 'unit vector' or misapplied it in concept, but I think that is the term for an object's heading when expressed as [x, y] when x and y are a value between -1 and 1; so if an object were moving 'south' on a computer screen, it would have a unit vector of

[0, 1]


Anyway, I've been using this concept to move my objects and rotate their images (when needed), but I think the math I'm using to determine the unit vector is... suboptimal.

def set_heading(self, goal):
    """Uses a 'goal' (x, y) to set the object's heading.
    Returns list of 0s and 1s for 'straight' headings.
    Diagonal headings are + and/or - math.sqrt(2)/2.
    vals = [a - b for a, b in zip(goal, self.pos)]
    self.heading = [i / abs(i) if i != 0 else 0 for i in vals]
    if 0 not in self.heading:
        self.heading = [i * (sqrt(2)/2) for i in self.heading]

(If you're not familiar with Python ternary syntax, the second line contains i / abs(i) if i != 0 else 0 which is Python's way of saying x if Condition else y as opposed to the usual Condition? x : else y syntax in other languages. Basically I'm just trying to avoid dividing by zero!)

So as you can see, this method of doing this sort of 'locks' the object into eight directions; if a 0 is not present in the heading, the method assumes that we're traveling diagonally and so multiplies the values by sqrt(2) / 2 to ensure that the object doesn't travel faster than it should when moving diagonally. In this way I can move the object by simply adding the result of the unit vector times its speed to its current x and y coordinates.

def move(self):
    """Moves the object by changing self.pos."""
    self.pos = [a + (b * self.speed) for a, b in zip(self.pos, self.heading)]

I can't help but feel like the method for getting the unit vector (if that's what it's correctly called) is sophomoric. Especially since it is locked into eight directions - it's fine for the little project I'm working with currently, but I'm not sure of the right method for getting a more precise unit vector. What is the correct method for doing so - and is it more or less performant than the weirdness I have come up with independently?

  • \$\begingroup\$ I don't have the time to write a fully fleshed out answer, but basically what you're supposed to do is substracting self from goal vectors, which gives you the vector between those two points. You then normalize it (i.e. divide by its magnitude), which results in the unit vector you want. Unit vector (or often "normalized vector") is not defined by having values between 0 and 1, but by having a length of exactly 1 unit - that both values end up being between 0 and 1 just follow from that. \$\endgroup\$
    – Christian
    Commented Sep 30, 2014 at 13:34
  • \$\begingroup\$ right. sorry, i guess i thought that understanding was expressed in the results of the method. A method that returns a diagonal (like 'southeast' for example) would return [.707, .707], rounded for sanity here b/c i'm not typing out the 15+ digits of sqrt(2)/2. But it would return coordinates which are 1 length away from [0, 0] which could be multiplied by the object's speed attribute to put it where it's headed \$\endgroup\$
    – Stick
    Commented Sep 30, 2014 at 14:16

1 Answer 1


A Unit Vector is of length 1.

A given vector can be converted to a unit vector by dividing it by it's magnitude. (With the exception of course that a zero length vector can not be converted).

Note that magnitude can be calculated using the Pythagorean theorem

For example if a vector has components: (x, y, z)

magnitude = sqrt( x2+ y2+ z2)

unit vector = ( x / magnitude , y / magnitude, z / magnitude )

Annan raises an interesting point that for vectors with a magnitude larger than math.sqrt(sys.float_info.max) (approximately 1.3e+154 on my machine) this will fail when using floats in the normal manner. In this case a workaround using longs to hold the working values and then finding the square root manually will be functional but relatively slow.

def isqrt(n):
    x = n
    y = (x + 1) // 2
    while y < x:
        x = y
        y = (x + n // x) // 2
    return x

def large_magnitude(x, y, z):
    long_magnitude_squared = pow(long(x), 2) + pow(long(y), 2) + pow(long(z), 2)
    return float(isqrt(long_magnitude_squared))

Credit for this implementation of Newton's Method goes to user448810.

  • \$\begingroup\$ ah, this is nice. Inevitable followup then -- would I ideally work to get the call to sqrt() out of the logic altogether (and thus no longer be working strictly with unit vectors) or is this an acceptable use for it \$\endgroup\$
    – Stick
    Commented Sep 30, 2014 at 14:19
  • 2
    \$\begingroup\$ Since you're working in python, I'd suggest - just use the sqrt and don't worry about it. \$\endgroup\$
    – amitp
    Commented Sep 30, 2014 at 15:11
  • \$\begingroup\$ hah, well - that's fine too, can I ask what that's meant to mean though? I hazard a guess; that Python's slow and that there's no ultimate upshot in trying to get around sqrt(). Which is fine -- I'm not coding for a living or anything :D \$\endgroup\$
    – Stick
    Commented Sep 30, 2014 at 18:46
  • 1
    \$\begingroup\$ @Stick Because Python is an interpreted language, so there is some overhead that is roughly equivalent to the number of commands executed. Internally Python use well optimised machine code, so the process of calculating the square root is not subject to this overhead. \$\endgroup\$ Commented Sep 30, 2014 at 19:24
  • 1
    \$\begingroup\$ @Annan I have added a workaround that will handle magnitudes up to sys.float_info.max (approximately 1.7e+308 on my machine) beyond that you will probably want to use a long based vector anyway. \$\endgroup\$ Commented Feb 2, 2017 at 9:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .