# Arithmetic/Geometric series calculator

I've written a small program that calculates Arithmetic and Geometric Partial Sums. I'd like feedback on anything possible, since I intend on writing a cheatsheet that encapsulates all PreCalculus equations.

partial_sum.py

"""
This is a program that calculates arithmetic and geometric
partial sums

"""

from fractions import Fraction

def find_an(parsed_series):
"""
Finds an in the passed parsed arithmetic series

:param parsed_series: The series to be analyzed

"""
for i, _ in enumerate(parsed_series):
if parsed_series[i] == ".":
return int(parsed_series[i + 1])
return None

def arithmetic_partial_sum(series):
"""
Returns the partial sum of an arithmetic series

Formula:
S = n( (a1 + an) / 2 )

Find an:
an = a1 + (n - 1)d

Find n:
n = 1 + ( (an - a1) / d )

:param series: Arithmetic series to solve

"""

series = series.split("+")

a1 = int(series)
d = int(series) - a1
an = find_an(series)
n = 1 + ((an - a1) / d)
S = n * ((a1 + an) / 2)

return S

def geometric_partial_sum(series):
"""
Returns the partial sum of the geometric series

:param series: Geometric series to solve

Formula:
S = (a1 * (1 - (r ** n))) / (1 - r)

"""

series = series.split("+")

a1 = int(series)
r = int(series) / a1
n = len(series)
S = (a1 * (1 - (r ** n))) / (1 - r)

return str(Fraction(S).limit_denominator())

if __name__ == '__main__':
A_SERIES = "3+7+11+15+.+99"
G_SERIES = f"3+1+{1/3}+{1/9}+{1/27}+{1/81}"
print(arithmetic_partial_sum(A_SERIES))
print(geometric_partial_sum(G_SERIES))


find_an() looks like an internal function, used by arithmetic_partial_sum(). If it is not for external use, it should be named with a leading underscore, to suggest it is private.

arithmetic_partial_sum() appears to handle only integer values, yet it return a floating-point value (1275.0 in the built-in example). It should return an integer, since it is adding up integers. Use the Python3.x integer-division operator: //.

    n = 1 + (an - a1) // d
S = n * (a1 + an) // 2


Or, not assume the terms are integer, and use float(...) instead.

geometric_partial_sum() fails if the first 2 values are not int values:

>>> geometric_partial_sum(f"1+{1/3}+{1/9}+{1/27}+{1/81}")
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
geometric_partial_sum(f"1+{1/3}+{1/9}+{1/27}+{1/81}")
File "...\partial_sum.py", line 63, in geometric_partial_sum
r = int(series) / a1
ValueError: invalid literal for int() with base 10: '0.3333333333333333'


You should convert the terms to floating-point values, not integers:

    a1 = float(series)
r = float(series) / a1


find_an() assumes $$\a_n\$$ is immediately after the '.' term, so will fail with:

arithmetic_partial_sum("3+7+11+15+.+95+99")
arithmetic_partial_sum("3+7+11+15+19")


Why not just retrieve the last term?

def find_an(parsed_series):
return int(parsed_series[-1])


Now the following all succeed and return the correct values

arithmetic_partial_sum("3+7+11+15+.+95+99")
arithmetic_partial_sum("3+7+11+15+...+95+99")
arithmetic_partial_sum("3+7+11+15+19")


The """docstrings""" for arithmetic_partial_sum() and geometric_partial_sum() appear unhelpful. For example:

>>> help(arithmetic_partial_sum)
Help on function arithmetic_partial_sum in module __main__:

arithmetic_partial_sum(series)
Returns the partial sum of an arithmetic series

Formula:
S = n( (a1 + an) / 2 )

Find an:
an = a1 + (n - 1)d

Find n:
n = 1 + ( (an - a1) / d )

:param series: Arithmetic series to solve


The function is not returning an or n. Even the formula is not particularly helpful. """docstrings""" should tell a user how to use the function. For example (adding Python 3.6 type hints as well):

def arithmetic_partial_sum(series:str) -> int:
"""
Returns the sum of an arithmetic series

Example:
s = arithmetic_partial_sum("1+3+5+.+99")  # returns 2500

:param series: A string representing the arithmetic series to solve
"""


Now type help(arithmetic_partial_sum):

>>> help(arithmetic_partial_sum)
Help on function arithmetic_partial_sum in module __main__:

arithmetic_partial_sum(series: str) -> int
Returns the sum of an arithmetic series

Example:
s = arithmetic_partial_sum("1+3+5+.+99")  # returns 2500

:param series: A string representing the arithmetic series to solve


The user is told the function takes a string and returns an integer. The format of the string should be clear from the example.