Проверка, существует ли не целое число в строке во время eval()

Приведен ввод различных схем уравнений в скобках в виде строки, например '(3-7)/5'Я смотрю, чтобы проверить, будет ли на каком-либо этапе его оценки содержать нецелое число.

Например, '(3/2)+1' немедленно содержит floatи остается float при полной оценке это существо 2.5, Но что-то вроде '(5/2)*2' кратко является числом с плавающей точкой, а затем может быть оценено как целое число, или, eval() функция, '(4/2)+3' после вычисления будет число с плавающей запятой, даже если во время оценки не существует нецелого числа.

Единственное, о чем я мог думать, пытаясь решить эту проблему, - это искать строку для / оператор, а затем найти наименьший набор скобок, который будет включать это деление. Таким образом, для '(2+1)/4' сначала нужно будет оценить 2+1 а затем может проверить на нецелое деление...

Какие-нибудь мысли?

1 ответ

К сожалению, есть слишком много вещей, которые могут привести к таким ценностям. Например ** может быть использован для вычисления квадратных корней и, как правило, содержимое передается eval может быть что угодно.

Я верю, используя eval это не очень хороший подход. Вы могли бы использовать ast.parse функция, чтобы получить AST (абстрактное синтаксическое дерево), которое представляет выражение, а затем написать свой собственный простой интерпретатор для его оценки. В этом переводчике вы можете делать все проверки, которые вы хотите на каждом этапе.


Вы бы написали что-то вроде:

from ast import *

def simple_expr_eval(expr):
    if not isinstance(expr, Expression):
        raise TypeError('should be an expression')
    return simple_eval(expr.body)

def simple_eval(expr):
    handlers = {
        BinOp: simple_eval_binop,
        UnaryOp: simple_eval_unaryop,
        Num: simple_eval_number,
        # ...
    }
    return handlers[type(expr)](expr)

def simple_eval_binop(binop):
    if binop.op is Mult:
        left = simple_eval(binop.left)
        right = simple_eval(binop.right):
        return left * right
    elif binop is Div:
        # here you could check whether left/right produces a floating point...
        raise ValueError('Floating operation during evaluation')
    # ...

Это немного работы, но на самом деле не так много, если вы хотите работать только с простыми выражениями. В этих функциях вы можете упростить / поменять местами узлы, чтобы изменить способ вычисления выражения.

Вы также должны проанализировать код, указав eval режим оценки (т.е. eval(your_expr, '<fake-filename>', 'eval')).

Другие вопросы по тегам