0

Assume the file containing a series of integers is named numbers.txt and exists on the computers disk. Write a program that reads all of the numbers stored in the file and calculates their total.

The program is not giving any errors back, but I'm getting the wrong total. I'm getting 5,750,884.00 and should be getting 284.00

This is what I've come up with so far:

def main():
    # Accumulator.
    total=0.0

    try:
        # Open the file
        infile = open('numbers.txt', 'r')
        #read the values from the file and accumulate them.
        for line in infile:
            amount = float(line)
            total+=amount

        # Close the file.
        infile.close()
    except exception as error:
        print(err)
    else:
        # Print the total.
        print(format(total,',.2f'))



main()    
Martijn Pieters
  • 889,049
  • 245
  • 3,507
  • 2,997
Luke Jones
  • 9
  • 1
  • 2
  • Ah, I missed the line where you gave the expected output. What input do you give the file? – Martijn Pieters Dec 16 '15 at 18:33
  • Your code looks correct to me; how do you know what the expected output is? – Martijn Pieters Dec 16 '15 at 18:34
  • I copy and pasted this code, created my own numbers.txt and it worked perfectly. – Dobz Dec 16 '15 at 18:36
  • The only errors I can see here wouldn't interfere with the sum you get; the unhelpful `except` block uses two different names for the exception it catches, and the file is closed in an exception-unsafe manner. – user2357112 supports Monica Dec 16 '15 at 18:37
  • I think it's a problem with your numbers.txt... – dot.Py Dec 16 '15 at 18:37
  • 2
    Do you get the same answer with this: `sum(map(int, open('numbers.txt')))`? Or if there could be more than one integer on a line and to ignore anything else; you could [use this](http://stackoverflow.com/a/20024735/4279). Though if lines are not very long and they contain only space-separated integers then `sum(i for line in open('numbers.txt') for i in map(int, line.split()))` also works. – jfs Dec 16 '15 at 18:57

3 Answers3

1
with open('numbers.txt', 'r') as f:
    print sum([float(x) for x in f.read().splitlines()])
Cody Bouche
  • 933
  • 5
  • 10
  • 1
    Elegant. Wouldn't this also work, and possibly be more efficient, without the list? Like this: `sum(float(x) for x in f.read().splitlines())` – Riccati Dec 16 '15 at 19:13
  • 4
    @Riccati: Actually, that's still wasteful, since it slurps the whole file into a `list`, using potentially huge amounts of memory, and delaying `sum` work until file slurped and split. Even better (basically zero memory overhead) is either `sum(float(x) for x in f)` or the absolute fastest (in Py3, or Py2 with `from future_builtins import map` to get Py3 `map`) `sum(map(float, f))`. It works even without stripping whitespace and newlines because `float` ignores leading and trailing whitespace anyway. – ShadowRanger Dec 16 '15 at 19:28
  • @ShadowRanger Thanks for the explanation. – Riccati Dec 16 '15 at 19:30
  • My teacher prefers we use the longer formats that the book gives us that way he knows we aren't just getting our answers from google. Thanks again. – Luke Jones Dec 16 '15 at 19:43
0

Use the with syntax for managing file closing, and use the sum function to add the items (with a generator expression)

try:
   with open('numbers.txt', 'r') as num_file:
      total = sum(float(l) for l in num_file)
   print('{:.2f}'.format(total))
except OSError as error:
   print('Error! (', error, ')')
except ValueError:
   print('File does not contain valid data')
Chad S.
  • 5,000
  • 11
  • 23
0

Since you're using Python 3 (presumably CPython), the absolute fastest solution is:

with open('numbers.txt') as f:
    total = sum(map(float, f))

In CPython, that pushes all of the work to the C layer (no matter the size of the file, same number of byte codes executed), and streams the file (so peak memory usage doesn't grow with file size).

When summing floats, you may want higher accuracy, which Python provides with math.fsum:

import math

with open('numbers.txt') as f:
    total = math.fsum(map(float, f))

It's slightly slower (not meaningfully; a matter of maybe 2% slower, give or take), but in exchange, it doesn't suffer from the additional loss of precision that generic summation of floats would incur due to storing partial sums with progressive rounding error.

ShadowRanger
  • 108,619
  • 9
  • 124
  • 184
  • My teacher prefers we use the longer formats that the book gives us that way he knows we aren't just getting out answers from google. Thanks again. I had program in the wrong folder. Guess I should always double check that. thanks again. – Luke Jones Dec 16 '15 at 19:43
  • it is not just "higher accuracy" -- `fsum()` may return an *accurate* sum without loss of precision if IEEE-754 arithmetic is available. Anyway, `int` should be used here: *"Assume the file containing a series of integers."* Also, [the task is IO bound](http://stackoverflow.com/questions/25606833/fastest-way-to-sum-integers-in-text-file#comment40064644_25606833). Otherwise, there are [faster ways](http://stackoverflow.com/questions/9371238/why-is-reading-lines-from-stdin-much-slower-in-c-than-python#comment11966378_9371238) to [read a file line by line than `map()`](https://goo.gl/Xc6jKC). – jfs Dec 26 '15 at 02:22