2013-07-21 2 views
0

숫자 사이에 피연산자를 무작위로 배치하는 파이썬 수식이 있습니다. 목록은, 예를 들어, 다음과 같이 수 :문자열 목록에서 계산 - Python

['9-8+7', '7-8-6'] 

는 내가 뭘 원하는 문자열을 통해 반복, 배열 9-8 + 7 참조 것이고 추가 것이다 있도록, 각 문자열의 값을 얻을 수있다 8과 7-8-6은 -7을 붙일 것이다. 피연산자가있는 문자열을 int로 변환 할 수 없으므로이 모든 것이 가능합니까? 또는 각 무작위 출력으로 문자열을 생성하는 대신 즉시 값을 계산하도록 알고리즘을 변경해야합니까?

미리 감사드립니다.

+2

그냥'+'와'-'입니까? –

답변

4

목록 항목에 eval을 할 수는 있지만 이는 잠재적 인 보안 허점이며 원본을 완전히 신뢰하는 경우에만 사용해야합니다. 당신이 값을 계산, 문자열을 생성하는 코드를 제어 할 경우

>>> map(eval, ['9-8+7', '7-8-6']) 
[8, -7] 

직접 (안전하고 아마 빨리) 더 나은 방법처럼 들린다.

1

물론 이것은 당신의 표현이 얼마나 잘 행동하고 제한되는지에 달려 있습니다.

빼기는 음수가 더해 지므로 빼기를 음수의 덧셈으로 쓸 수 있습니다. 용어를 찾으려면 +를 누르십시오. 그런 다음 합계의 조건을 정수로 구문 분석하고 합계합니다. 각 표현식에 대해 그렇게하십시오.

[sum(map(int,l.replace('-', '+-').split('+'))) for l in ['9-8+7','7-8-6']] 
2

Fredrik이 지적한 것처럼, eval은 Python으로 처리 할 수 ​​있습니다. 어떤 언어로든 작동 할 수있는 좀 더 일반적인 접근법을 추가 할 것이라고 생각했으며, 실제로 작동하지 않는 사람들을 위해 간단한 파서를 밝힐 수 있습니다. * "3", "4 :

expr := sum 
sum := prod [("+" | "-") prod]... 
prod := digit [("*" | "/") digit]... 
digit := '0'..'9' 

(I 올바른 EBNF을 귀찮게하고 있지 않다)이 문법은 이러한 문자열을 받아 :

당신은 누구의 공식적인 정의를 다음과 같이 보입니다 언어를 설명하고 5/2 "및"8 * 3 + 9 "등이 있습니다.

이것은 파싱하는 방법에 대한 단서를 제공하며, 평가는 우리가 갈 때 결과를 누적하는 것 이상입니다. 다음은 Python 2 코드를 사용하고있다. 코드가 문법을 얼마나 가깝게 따르는 지 확인하십시오.

class ParseFail(Exception): 
    pass 

def eval_expr(str): 
    value, pos = eval_sum(str, 0) 
    return value 

def eval_sum(str, pos): 
    value, pos = eval_product(str, pos) 
    accum = value 
    while pos != len(str): 
     op = str[pos] 
     if not str[pos] in ['+', '-']: 
      raise ParseFail("Unexpected symbol at position " 
          "{pos} of {str}".format(str=str, pos=pos)) 
     value, pos = eval_product(str, pos + 1) 
     if op == '+': 
      accum += value 
     else: 
      accum -= value 
    return accum, pos 

def eval_product(str, pos): 
    value, pos = eval_digit(str, pos) 
    accum = value 
    while pos != len(str): 
     op = str[pos] 
     if not str[pos] in ['*', '/']: 
      return accum, pos 
     value, pos = eval_digit(str, pos + 1) 
     if op == '*': 
      accum *= value 
     else: 
      accum /= value 
    return accum, pos 

def eval_digit(str, pos): 
    if not str[pos].isdigit(): 
     raise ParseFail("Unexpected symbol at position " 
         "{pos} of {str}".format(str=str, pos=pos)) 
    return int(str[pos]), pos + 1 

try: 
    print "3 ->", eval_expr("3") 
    print "3*4 ->", eval_expr("3*4") 
    print "2+3*4-5 ->", eval_expr("2+3*4-5") 

    # Should raise ParseFail 
    print "2+3*4^2-5 ->", eval_expr("2+3*4^2-5") 
except ParseFail as err: 
    print 
    print err.args[0] 

여기 샘플 실행의 :

$ python simple_expr.py 
3 -> 3 
3*4 -> 12 
2+3*4-5 -> 9 
2+3*4^2-5 -> 
Unexpected symbol at position 5 of 2+3*4^2-5 

이는 지수 연산자 '^'와 여러 자리의 정수로 더 연산자로 전체 문자열 계산기이를 확장하는 매우 쉬운 것입니다. 괄호, 수레 및 함수는 약간의 작업 일지 모르지만 그다지 어렵지는 않습니다. 모든 프로그래머는 내 의견으로는 한 번 시도해 봐야합니다.

관련 문제