pythonstringdecimalfloating-point-conversion

print sum of strings as float


I am working on an exercise that states:

Let s be a string that contains a sequence of decimal numbers separated by commas, e.g., s = '1.23,2.4,3.123'. Write a program that prints the sum of the numbers in s.

My solution is:

s = '1.23,2.4,3.123'
news = s + ","
value = ""
floatValue = 0


for i in range(len(news)):
    if news[i] != ',':
        value += s[i]
    elif news[i] == ',':
        floatValue += float(value)
        value = ""

print floatValue

I was just wondering if there is a more efficient way to do this? Also I'm in the beginning of a Python course so at this point I am only trying to accomplish this with a beginner-level solution.


Solution

  • Yes, significantly:

    >>> s = '1.23,2.4,3.123'
    >>> sum(map(float, s.split(",")))
    6.753
    

    This uses str.split to divide the string up into numbers:

    >>> s.split(",")
    ['1.23', '2.4', '3.123']
    

    map to apply float to each string

    >>> map(float, s.split(","))
    [1.23, 2.4, 3.123]
    

    and sum to add up the total.


    As there are several answers with slightly different approaches, I thought I'd test them out to see which was most efficient:

    2.7.6

    >>> import timeit
    >>> def f1(s):
        return sum(map(float, s.split(",")))
    
    >>> def f2(s):
        return sum(float(x) for x in s.split(","))
    
    >>> def f3(s):
        return sum([float(x) for x in s.split(",")])
    
    >>> timeit.timeit("f1(s)", setup="from __main__ import f1, f2, f3;s='1.23,2.4,3.123'")
    2.627161979675293
    >>> timeit.timeit("f2(s)", setup="from __main__ import f1, f2, f3;s='1.23,2.4,3.123'")
    2.805773973464966
    >>> timeit.timeit("f3(s)", setup="from __main__ import f1, f2, f3;s='1.23,2.4,3.123'")
    2.6547701358795166
    

    3.4.0

    >>> timeit.timeit("f1(s)", setup="from __main__ import f1, f2, f3;s='1.23,2.4,3.123'")
    2.3012791969995305
    >>> timeit.timeit("f2(s)", setup="from __main__ import f1, f2, f3;s='1.23,2.4,3.123'")
    3.1761953750028624
    >>> timeit.timeit("f3(s)", setup="from __main__ import f1, f2, f3;s='1.23,2.4,3.123'")
    3.1163038839986257
    

    Bonus round for Ashwini (3.4.0):

    >>> from ast import literal_eval
    >>> def f4(s):
        return sum(literal_eval(s))
    
    >>> timeit.timeit("f4(s)", setup="from __main__ import f1, f2, f3, f4;s='1.23,2.4,3.123'")
    23.054055102998973
    >>> timeit.timeit("f1(s)", setup="from __main__ import f1, f2, f3, f4;s='1.23,2.4,3.123'")
    2.2302689969983476
    

    This works (slowly!) using ast.literal_eval to interpret the string as a tuple of floats:

    >>> literal_eval('1.23,2.4,3.123')
    (1.23, 2.4, 3.123)