-1

My code:

distance = ['0.12', '0.02', '0.13', '0.02', '0.13', '0.02', '0.13', '0.02', '0.12', '0.01', '0.13', '0.02', '0.12', '0.02', '0.12', '0.02', '0.13', '0.02', '0.13', '0.02', '0.12', '0.02', '0.13', '0.02', '0.13', '0.02', '0.13', '0.02', '0.13', '0.02', '0.13', '0.02', '0.13', '0.02', '0.13', '0.01', '0.13', '0.02', '0.13', '0.01']

the values are from a CSV file and appending it to distance list. how do I sum them so I can get a total distance? I've tried some of the answers given on the website but they haven't worked :(

poke
  • 369,085
  • 72
  • 557
  • 602

3 Answers3

5

Convert the strings to floats using map, and then sum the resulting numbers with sum.

>>> sum(map(float, distance))
2.9199999999999986

Those 9s are due to the inherent imprecision of floats. If you want something exact, you can use Decimal.

>>> from decimal import Decimal
>>> sum(map(Decimal, distance))
Decimal('2.92')
Kevin
  • 74,910
  • 12
  • 133
  • 166
  • A generator expression might be considered more Pythonic: `sum( float(x) for x in distance)`. – chepner Feb 06 '14 at 16:26
  • 1
    @chepner : why? would you replace all usage of `map` by a generator? (itertools.imap would return a generator as well, hence eliminating the creation of the list `map` returns, too) – njzk2 Feb 06 '14 at 16:28
  • 1
    You can use `math.fsum` instead of `sum` to get more accurate results. – Ashwini Chaudhary Feb 06 '14 at 16:28
  • @njzk2 http://stackoverflow.com/q/1247486/1126841 – chepner Feb 06 '14 at 16:30
  • Using `map` (or imap) is a lot more efficient, as you are *not* interested in the resulting list. See also my answer on [this question](http://stackoverflow.com/questions/21501174/length-of-all-string-in-the-list-the-fastest-way/21501588#21501588). – poke Feb 06 '14 at 16:44
  • Good idea, @AshwiniChaudhary. In this particular instance, `fsum` gives a result that is two decimal places more accurate. The practical difference being, it gets displayed as `2.92` when printed. (although in reality it's actually represented as `2.9199999999999999289457264239899814128875732421875`) – Kevin Feb 06 '14 at 16:47
4

Convert each element to a float and use the sum builtin:

distance = ['0.12', '0.02', '0.13', '0.02', '0.13', '0.02', '0.13', '0.02', '0.12', '0.01', '0.13', '0.02', '0.12', '0.02', '0.12', '0.02', '0.13', '0.02', '0.13', '0.02', '0.12', '0.02', '0.13', '0.02', '0.13', '0.02', '0.13', '0.02', '0.13', '0.02', '0.13', '0.02', '0.13', '0.02', '0.13', '0.01', '0.13', '0.02', '0.13', '0.01']

distance = [float(s) for s in distance]
total = sum(distance)

total
>>> 2.9199999999999986

To take care of the extra 9s, use Decimal.

from decimal import Decimal

distance = [Decimal(s) for s in distance]
total = sum(distance)
total
>>>Decimal('2.92')
That1Guy
  • 7,075
  • 4
  • 47
  • 59
3

Before you use the built-in sum you need to convert the string values to floats.

This does not work:

>>> sum(['1', '2'])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'

But this does:

>>> sum([1,2])
3

Therefor you need to step through every value of your list distance and convert to a float before handing the list to sum.

You can use a list comprehension, map, a loop or a generator expression:

>>> distance = ['0.12', '0.02', '0.13', '0.02', '0.13', '0.02', '0.13', '0.02', '0.12', '0.01', '0.13', '0.02', '0.12', '0.02', '0.12', '0.02', '0.13', '0.02', '0.13', '0.02', '0.12', '0.02', '0.13', '0.02', '0.13', '0.02', '0.13', '0.02', '0.13', '0.02', '0.13', '0.02', '0.13', '0.02', '0.13', '0.01', '0.13', '0.02', '0.13', '0.01']
>>> sum(float(e) for e in distance)
2.9199999999999986

For a more accurate result, use fsum:

>>> math.fsum(float(e) for e in distance)
2.92    
dawg
  • 98,345
  • 23
  • 131
  • 206
  • Technically, this is a generator expression, as no list is created as would be with `sum([float(e) for e in distance])`. – chepner Feb 06 '14 at 16:27