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

Search Discussions

  • Chris Rebert at May 30, 2011 at 9:24 am

    On Mon, May 30, 2011 at 2:11 AM, 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.

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

    Cheers,
    Chris
  • Peter Otten at May 30, 2011 at 9:46 am

    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
  • Gabriel Genellina at May 30, 2011 at 7:01 pm
    En Mon, 30 May 2011 06:46:01 -0300, Peter Otten <__peter__ at web.de>
    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
  • Gabriel at Jun 1, 2011 at 7:35 pm

    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.
  • Gabriel at May 30, 2011 at 1:38 pm
    Thanks a lot to both of you, Chris & Peter!

    (I knew the solution would be simple ... ;-) )
  • Algis Kabaila at Jun 2, 2011 at 9:26 pm

    On Monday 30 May 2011 23:38:53 Gabriel wrote:
    Thanks a lot to both of you, Chris & Peter!

    (I knew the solution would be simple ... ;-) )
    import math
    length = math.hypot(z, math.hypot(x, y))

    One line and fast.

    OldAl.
  • Ian Kelly at Jun 2, 2011 at 11:19 pm

    On Thu, Jun 2, 2011 at 3:26 PM, Algis Kabaila 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
  • Gabriel at Jun 3, 2011 at 9:53 pm

    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.
  • Ian Kelly at Jun 3, 2011 at 10:17 pm

    On Fri, Jun 3, 2011 at 3:53 PM, Gabriel 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
  • Robert Kern at Jun 3, 2011 at 11:12 pm

    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

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedMay 30, '11 at 9:11a
activeJun 3, '11 at 11:12p
posts11
users7
websitepython.org

People

Translate

site design / logo © 2022 Grokbase