Best way to compute length of arbitrary dimension vector?

G

Gabriel

Well, the subject says it almost all: I'd like to write a small Vector
class for arbitrary-dimensional vectors.

I am wondering what would be the most efficient and/or most elegant
way to compute the length of such a Vector?

Right now, I've got

def length(self): # x.length() = || x ||
total = 0.0
for k in range(len(self._coords)):
d = self._coords[k]
total += d*d
return sqrt(total)

However, that seems a bit awkward to me (at least in Python ;-) ).

I know there is the reduce() function, but I can't seem to find a way
to apply that to the case here (at least, not without jumping through
too many hoops).

I have also googled a bit, but found nothing really elegant.

Any ideas?

Best regards,
Gabriel.
 
C

Chris Rebert

Well, the subject says it almost all: I'd like to write a small Vector
class for arbitrary-dimensional vectors.

I am wondering what would be the most efficient and/or most elegant
way to compute the length of such a Vector?

Right now, I've got

 def length(self):                                                                                     # x.length() = || x ||
   total = 0.0
   for k in range(len(self._coords)):
     d = self._coords[k]
     total += d*d
   return sqrt(total)

However, that seems a bit awkward to me (at least in Python ;-) ).

I know there is the reduce() function, but I can't seem to find a way
to apply that to the case here (at least, not without jumping through
too many hoops).

I have also googled a bit, but found nothing really elegant.

Any ideas?

def length(self):
return sqrt(sum(coord*coord for coord in self._coords))

Cheers,
Chris
 
P

Peter Otten

Gabriel said:
Well, the subject says it almost all: I'd like to write a small Vector
class for arbitrary-dimensional vectors.

I am wondering what would be the most efficient and/or most elegant
way to compute the length of such a Vector?

Right now, I've got

def length(self): # x.length() = || x ||
total = 0.0
for k in range(len(self._coords)):
d = self._coords[k]
total += d*d
return sqrt(total)

However, that seems a bit awkward to me (at least in Python ;-) ).

I know there is the reduce() function, but I can't seem to find a way
to apply that to the case here (at least, not without jumping through
too many hoops).

I have also googled a bit, but found nothing really elegant.
.... def __init__(self, *coords):
.... self._coords = coords
.... def __abs__(self):
.... return math.sqrt(sum(x*x for x in self._coords))
....5.0
 
G

Gabriel

Thanks a lot to both of you, Chris & Peter!

(I knew the solution would be simple ... ;-) )
 
G

Gabriel Genellina

... def __init__(self, *coords):
... self._coords = coords
... def __abs__(self):
... return math.sqrt(sum(x*x for x in self._coords))
...
5.0

Using math.fsum instead of sum may improve accuracy, specially when
len(coords)≫2

py> import math
py>
py> def f1(*args):
.... return math.sqrt(sum(x*x for x in args))
....
py> def f2(*args):
.... return math.sqrt(math.fsum(x*x for x in args))
....
py> pi=math.pi
py> args=[pi]*16
py> abs(f1(*args)/4 - pi)
4.4408920985006262e-16
py> abs(f2(*args)/4 - pi)
0.0
 
I

Ian Kelly

import math

length = math.hypot(z, math.hypot(x, y))

One line and fast.

The dimension is arbitrary, though, so:

length = reduce(math.hypot, self._coords, 0)

Cheers,
Ian
 
G

Gabriel

The dimension is arbitrary, though, so:

length = reduce(math.hypot, self._coords, 0)


Thanks, I was going to ask Algis that same question.

But still, is this solution really faster or better than the one using
list comprehension and the expression 'x*x'?
It seems to me that the above solution (using hypot) involves repeated
square roots (with subsequent squaring).

Best regards,
Gabriel.
 
I

Ian Kelly

But still, is this solution really faster or better than the one using
list comprehension and the expression 'x*x'?

No, not really.
c:\python32\python -m timeit -s "coords = list(range(100))" -s "from math import hypot" -s "from functools import reduce" "reduce(hypot, coords, 0)"
10000 loops, best of 3: 53.2 usec per loop
c:\python32\python -m timeit -s "coords = list(range(100))" -s "from math import sqrt, fsum" "sqrt(fsum(x*x for x in coords))"
10000 loops, best of 3: 32 usec per loop
c:\python32\python -m timeit -s "coords = list(range(100))" -s "from math import sqrt" "sqrt(sum(x*x for x in coords))"
100000 loops, best of 3: 14.4 usec per loop
 
R

Robert Kern

Thanks, I was going to ask Algis that same question.

But still, is this solution really faster or better than the one using
list comprehension and the expression 'x*x'?
It seems to me that the above solution (using hypot) involves repeated
square roots (with subsequent squaring).

It also means that the floating point numbers stay roughly the same size, so you
will lose less precision as the number of elements goes up. I don't expect the
number of elements will be large enough to matter, though.

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,190
Members
46,736
Latest member
zacharyharris

Latest Threads

Top