在没有任何内置eval函数或外部库的python中解决数学问题

时间:2014-02-05 09:37:36

标签: python math

我需要编写一个可以从这个

获取值的程序

2 个答案:

答案 0 :(得分:3)

非常有趣的问题。实际上,在你的情况下,它很简单。您可以使用ast模块解析整个源字符串,如此

import ast
import operator

functions = {
    "add": operator.add,
    "abs": operator.abs,
    "multiply": operator.mul
}

def recursive_evaluation(current_element):
    if isinstance(current_element, ast.Module):
        return recursive_evaluation(current_element.body[0].value)
    elif isinstance(current_element, ast.Call):
        function = functions[current_element.func.id]
        args = [recursive_evaluation(item) for item in current_element.args]
        return function(*args)
    elif isinstance(current_element, ast.Num):
        return current_element.n
    else:
        raise ValueError("Unknown Element " + str(current_element))

source = "abs(add(add(9465,38),multiply(add(63303,146),46)))"
print recursive_evaluation(ast.parse(source))

source = "add(1, -2)"
print recursive_evaluation(ast.parse(source))

source = "abs(add(1, -2))"
print recursive_evaluation(ast.parse(source))

<强>输出

2928157
-1
1

答案 1 :(得分:0)

有趣的问题,这是一个潜在的解决方案。毫无疑问,你可以使用库或lambdas等制作一个更优雅的解决方案,就像他们在答案中所做的那样,但这似乎有效。

我在底部做了一些测试用例,如果你想要调试信息,请将全局verbose设置为True

# globals
verbose = False # set to True if you want debug info printed
max_iter = 1000 # this stops infinate loops incase the code does not allow for some input

def solve(problem_str):

    def multiply(arg_list):
        x = 1
        for i in arg_list:
            x *= i
        return x

    def find_innermost(x_str):
        a, b, c, i = [0], [0], 0, 0
        while True:
            i += 1
            start = a[-1]+1
            a.append(x_str.find('(', start)) # find next (
            b.append(x_str.find(',', start)) # find next ,
            c = x_str.find(')', start)       # find next )
            if (a[-1] > c) or (a[-1] == -1):
                if (b[-2] > a[-3]) and (b[-2] < a[-2]):
                    return x_str[b[-2]+1:c+1]
                else:
                    return x_str[a[-3]+1:c+1] 
            if i >= max_iter:
                raise Exception("Infinite loop")

    def do_sum(x_str):
        args = [int(x) for x in x_str[x_str.find('(')+1:x_str.find(')')].split(',')]
        task = x_str[:3].lower()
        if task == 'add':
            return sum(args)
        elif task == 'sub':
            return args[0] - sum(args[1:])
        elif task == 'abs':
            return abs(args.pop())
        elif task == 'mul':
            return multiply(args)
        else:
            print x_str + ': Task not recognised, please modify program or input'
            raise Exception("Invalid input")

    i = 0
    while True:
        i += 1
        if verbose: print 'debug: problem_str:', problem_str
        if problem_str.count('(') > 1:
            x_str = find_innermost(problem_str)
        else:
            x_str = problem_str
        if verbose: print '.'*6, 'x_str:\t', x_str
        x = do_sum(x_str)
        if verbose: print '.'*6, 'x:\t', x, '\n'
        problem_str = problem_str.replace(x_str, str(x))
        if problem_str.count('(') == 0:
            return int(problem_str)
        if i >= max_iter:
            raise Exception("Infinite loop")

if __name__ == '__main__':
    p1 = 'abs(add(add(9465,38),multiply(add(63303,146),46)))'
    p2 = 'abs(add(multiply(95,multiply(-1,multiply(13,18875))),multiply(-1,add(18293,26))))'
    p3 = 'abs(add(subtract(add(add(151,26875),122),254),subtract(237,multiply(-1,56497))))'
    r1, r2, r3 = solve(p1), solve(p2), solve(p3)
    print 'p1 evaluates to:', r1
    print 'p2 evaluates to:', r2
    print 'p3 evaluates to:', r3

如果您对代码有任何疑问,请与我们联系。