2015-01-31 10 views
1

저는 입력 방정식과 입력 변수를 사용하여 합계를 취하는 sigsum() 함수를 만듭니다. 여기에 지금까지 가지고 무엇 : 기능의setattr()을 사용하여 문자열을 변수로 변환

def sigsum(eqn, index, lower=0, upper=None, step=1): 

    if type(step) is not int: 
     raise TypeError('step must be an integer') 
    elif step < 1: 
     raise ValueError('step must be greater than or equal to 1') 

    if upper is None: 
     upper = 1280000 

    if lower is None: 
     lower = -1280000 

    if (upper - lower) % step: 
     upper -= (upper - lower) % step 

    index = lower 
    total = 0 
    while True: 
     total += eqn 
     if index == upper: 
      break 
     index += step 

    return total 

사용법 :

print(sigsum('1/(i+5)','i')) 
>>> 12.5563 

내 현재의 문제는 기능 지역 이름 공간 안에 존재하는 변수 '는 식'과 '지수'로 변환된다. 나는 exec를 사용하는 것이 좋은 생각이 아니며 아마도 setattr()이 작동 할 수도 있다고 들었다. 누구든지 나를 도울 수 있습니까? 감사합니다. . eqn를 들어 내가 람다 함수를 사용하는 것이 좋습니다

답변

2

: 그냥 "함수에 전달 된 변수"이기 때문에

eqn = lambda i: 1/(i + 5) 

다음 index가 필요하지 않습니다 (이름이 필요하지 않습니다).

는 그런 다음 기능은

def integrate(fn, start = 0, end = 128000, step = 1): 
    """ 
    Return a stepwise approximation of 
     the integral of fn from start to end 
    """ 
    num_steps = (end - start) // step 
    if num_steps < 0: 
     raise ValueError("bad step value") 
    else: 
     return sum(fn(start + k*step) for k in range(num_steps)) 

이되고이 많은 단계가 있다는 것을

res = step_integrate(eqn) # => 10.253703030104417 

주처럼 실행할 수 있으며, 그들 중 많은 사람들이 매우 작은 숫자를 포함; 반올림 오류가 주요 문제가 될 수 있습니다. 정확도가 중요한 경우, 수동으로 통합을 유도하기 위해 다시

res = step_integrate(eqn) # => 10.150386692204735 

처럼 실행

from math import log 

eqn   = lambda i: 1/(i + 5) 
eqn.integral = lambda i: log(i + 5) 

def integrate(fn, start = 0, end = 128000, step = 1): 
    """ 
    Return the integral of fn from start to end 

    If fn.integral is defined, used it; 
    otherwise do a stepwise approximation 
    """ 
    if hasattr(fn, "integral"): 
     return fn.integral(end) - fn.integral(start) 
    else: 
     num_steps = (end - start) // step 
     if num_steps < 0: 
      raise ValueError("bad step value") 
     else: 
      return sum(fn(start + k*step) for k in range(num_steps)) 

을 할 수 있습니다 (단계별 근사치는 약 1 % 너무 높았다 있습니다.)

+0

ok. 나는 그런 생각을하지 않았다. 만약 내가 람다를 사용한다면 어떻게 나중에 eqn을 부를 수 있을까요? 현재 sigsum()이 여전히 작동합니까? –

1

I을 휴 보스 웰 당신을 제안 람다 기능을 사용 다음

def sigsum(eqn, lower=0, upper=None, step=1): 

    if type(step) is not int: 
     raise TypeError('step must be an integer') 
    elif step < 1: 
     raise ValueError('step must be greater than or equal to 1') 

    if upper is None: 
     upper = 1280000 

    if lower is None: 
     lower = -1280000 

    if (upper - lower) % step: 
     upper -= (upper - lower) % step 

    index = lower 
    total = 0 
    while True: 
     total += eqn(index) 
     if index == upper: 
      break 
     index += step 

    return total 
로 sigsum을 수정해야 할 것입니다 기능의

사용법 : 당신은 또한 separatly 함수 정의 할 수 있습니다

print(sigsum(lambda i: 1/(i+5))) 
>>> 12.5563 

:

def myfunction(i): 
    return 1/(i+5) 

을하고 통과가

print(sigsum(myfunction)) 
>>> 12.5563 

이 매개 변수가 같은 기능을 통과 할 수 있도록 sigsum하기 컴퓨터 언어 음성 기능을 일급 대상이라고합니다. (예를 들어, C와 java에는 javacript와 python이 없습니다.)

+0

감사합니다. 대단한 도움들. 나는 setattr()이 필요 없다고 생각한다. 'eqn'의 경우 : 다른 곳에서 정의한 함수를 입력하면 작동합니까? –

+0

끝내 주셔서 고맙습니다. –