Sympy seems to break down with higher numbers
Question: I've been playing around with sympy and decided to make an arbitrary equations
solver since my finance class was getting a little dreary. I wrote a basic
framework and started playing with some examples, but some work and some don't
for some reason.

    
    
    from sympy import *
    import sympy.mpmath as const
    
    OUT_OF_BOUNDS = "Integer out of bounds."
    INVALID_INTEGER = "Invalid Integer."
    INVALID_FLOAT = "Invalid Float."
    CANT_SOLVE_VARIABLES = "Unable to Solve for More than One Variable."
    CANT_SOLVE_DONE = "Already Solved. Nothing to do."
    
    # time value of money equation: FV = PV(1 + i)**n
    # FV = future value
    # PV = present value
    # i = growth rate per perioid
    # n = number of periods
    FV, PV, i, n = symbols('FV PV i n')
    time_value_money_discrete = Eq(FV, PV*(1+i)**n)
    time_value_money_continuous = Eq(FV, PV*const.e**(i*n))
    
    def get_sym_num(prompt, fail_prompt):
        while(True):
            try:
                s = input(prompt)
                if s == "":
                    return None
                f = sympify(s)
                return f
            except:
                print(fail_prompt)
                continue
    
    equations_supported = [['Time Value of Money (discrete)', [FV, PV, i, n], time_value_money_discrete], 
                           ['Time Value of Money (continuous)',[FV, PV, i, n], time_value_money_continuous]]
    EQUATION_NAME = 0
    EQUATION_PARAMS = 1
    EQUATION_EXPR = 2
    
    if __name__ == "__main__":
        while(True):
            print()
            for i, v in enumerate(equations_supported):
                print("{}: {}".format(i, v[EQUATION_NAME]))
            try:
                process = input("What equation do you want to solve?  ")
                if process == "" or process == "exit":
                    break
                process = int(process)
            except:
                print(INVALID_INTEGER)
                continue
            if process < 0 or process >= len(equations_supported):
                print(OUT_OF_BOUNDS)
                continue
            params = [None]*len(equations_supported[process][EQUATION_PARAMS])
            for i, p in enumerate(equations_supported[process][EQUATION_PARAMS]):
                params[i] = get_sym_num("What is {}? ".format(p), INVALID_FLOAT)
            if params.count(None) > 1:
                print(CANT_SOLVE_VARIABLES)
                continue
            if params.count(None) == 0:
                print(CANT_SOLVE_DONE)
                continue
            curr_expr = equations_supported[process][EQUATION_EXPR]
            for i, p in enumerate(params):
                if p != None:
                    curr_expr = curr_expr.subs(equations_supported[process][EQUATION_PARAMS][i], params[i])
            print(solve(curr_expr,  equations_supported[process][EQUATION_PARAMS][params.index(None)]))
    

This is the code I have so far. I guess I can strip it down to a basic example
if need be, but I was also wondering if there was a better way to implement
this sort of system. After I have this down, I want to be able to add
arbitrary equations and solve them after inputting all but one parameter.

For example, if I put in (for equation 0), FV = 1000, PV = 500, i = .02, n is
empty I get 35.0027887811465 which is the correct answer. If I redo it and
change FV to 4000, it returns an empty list as the answer.

Another example, when I input an FV, PV, and an n, the program seems to hang.
When I input small numbers, I got RootOf() answers instead of a simple
decimal.

Can anyone help me?

Side note: I'm using SymPy 0.7.6 and Python 3.5.1 which I'm pretty sure are
the latest


Answer: This is a floating point accuracy issue. `solve` by default plugs solutions
into the original equation and evaluates them (using floating point
arithmetic) in order to sort out false solutions. You can disable this by
setting `check=False`. For example, for Hugh Bothwell's code

    
    
    for fv in range(1870, 1875, 1):
        sols = sp.solve(eq.subs({FV:fv}), check=False)
        print("{}: {}".format(fv, sols))
    

which gives

    
    
    1870: [66.6116466112007]
    1871: [66.6386438584579]
    1872: [66.6656266802551]
    1873: [66.6925950919998]
    1874: [66.7195491090752]
    

