Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Best way to compute length of arbitrary dimension vector?

Reply
Thread Tools

Best way to compute length of arbitrary dimension vector?

 
 
Gabriel
Guest
Posts: n/a
 
      05-30-2011
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.
 
Reply With Quote
 
 
 
 
Chris Rebert
Guest
Posts: n/a
 
      05-30-2011
On Mon, May 30, 2011 at 2:11 AM, Gabriel <(E-Mail Removed)> wrote:
> 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
--
http://rebertia.com
 
Reply With Quote
 
 
 
 
Peter Otten
Guest
Posts: n/a
 
      05-30-2011
Gabriel wrote:

> 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.


>>> class Vector(object):

.... def __init__(self, *coords):
.... self._coords = coords
.... def __abs__(self):
.... return math.sqrt(sum(x*x for x in self._coords))
....
>>> import math
>>> abs(Vector(1,1))

1.4142135623730951
>>> abs(Vector(3,4))

5.0


 
Reply With Quote
 
Gabriel
Guest
Posts: n/a
 
      05-30-2011
Thanks a lot to both of you, Chris & Peter!

(I knew the solution would be simple ... )
 
Reply With Quote
 
Gabriel Genellina
Guest
Posts: n/a
 
      05-30-2011
En Mon, 30 May 2011 06:46:01 -0300, Peter Otten <(E-Mail Removed)>
escribió:

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

>
>>>> class Vector(object):

> ... def __init__(self, *coords):
> ... self._coords = coords
> ... def __abs__(self):
> ... return math.sqrt(sum(x*x for x in self._coords))
> ...
>>>> import math
>>>> abs(Vector(1,1))

> 1.4142135623730951
>>>> abs(Vector(3,4))

> 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


--
Gabriel Genellina

 
Reply With Quote
 
Gabriel
Guest
Posts: n/a
 
      06-01-2011
> py> def f2(*args):
> ... * return math.sqrt(math.fsum(x*x for x in args))


Wow! Thanks a million - I didn't now about math.fsum!

Best regards,
Gabriel.
 
Reply With Quote
 
Ian Kelly
Guest
Posts: n/a
 
      06-02-2011
On Thu, Jun 2, 2011 at 3:26 PM, Algis Kabaila <(E-Mail Removed)> wrote:
> 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
 
Reply With Quote
 
Gabriel
Guest
Posts: n/a
 
      06-03-2011

> 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.
 
Reply With Quote
 
Ian Kelly
Guest
Posts: n/a
 
      06-03-2011
On Fri, Jun 3, 2011 at 3:53 PM, Gabriel <(E-Mail Removed)> wrote:
> 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
 
Reply With Quote
 
Robert Kern
Guest
Posts: n/a
 
      06-03-2011
On 6/3/11 4:53 PM, Gabriel wrote:
>
>> 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).


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

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
FAQ 4.43 How do I compute the difference of two arrays? How do I compute the intersection of two arrays? PerlFAQ Server Perl Misc 0 02-02-2011 05:00 AM
a question about 1-dimension and 2-dimension array Luuk C Programming 15 02-11-2010 02:45 AM
arbitrary dimension array for math Dimitri Ognibene Java 7 08-08-2006 11:00 AM
arrays of arbitrary dimension? wpegden@hotpop.com Perl Misc 3 03-23-2006 05:51 AM
newbie question : picture dimension vs print dimension Rene Wong Digital Photography 9 09-30-2003 01:46 AM



Advertisments