EPI00 개발일지

삼각함수+다항함수 정적분 (파이썬, 코드 only) 본문

프로그램 개발?

삼각함수+다항함수 정적분 (파이썬, 코드 only)

EPI00 2021. 7. 25. 12:36

이전에 C++로 다항함수를 구분구적법을 이용해 정적분 값을 구하는 코드를 짰었다. 
솔직히 삼각함수도 가능은 했었는데 그걸 굳이 C++로 만드는 건 시간 낭비라 생각했고, 
오늘은 삼각함수도 가능한 코드를 파이썬으로 작성했다. 

사용 언어 : Python 3.7.4
제작 기간 : 2021년 07월 25일 오전 11시 ~ 오후 12시 10분

코드 : 

더보기
import math

A = 0.000001

tfs = ['sin', 'cos', 'tan', 'sec', 'csc', 'cot']

def f(a, l):
    r = 0
    wast = False
    for i in range(len(l)):
        if wast:
            wast=False
            continue
        s = l[i]
        t = False
        for j in tfs:
            if j == s:
                t = True
        if t: #삼각함수
            wast = True
            s2 = l[i+1][:-1]
            if '.' in s2:
                asdf = s2.split('.')
                it,up = int(asdf[0]),int(asdf[1]) #InTager, UnderPoint
                asd = it
                asd += up * ((0.1)**len(asdf[1]))
            else:
                if s2 =='':
                    asd = 1
                else:
                    asd = int(s2)
            if s == 'sin':
                r += math.sin(asd*a)
            elif s == 'cos':
                r += math.cos(asd*a)
            elif s == 'tan':
                r += math.tan(asd*a)
            elif s == 'sec':
                r += 1/(math.cos(asd*a))
            elif s == 'csc':
                r += 1/(math.sin(asd*a))
            elif s == 'cot':
                r += 1/(math.tan(asd*a))
        else: #다항함수
            if '^' in s:
                ss = s.split('x^')
                if '.' in ss[0]:
                    asdf = ss[0].split('.')
                    it, up = int(asdf[0]),int(asdf[1])
                    asd = it
                    asd += up * ((0.1)**len(asdf[1]))
                else:
                    if ss[0] =='':
                        asd = 1
                    else:
                        asd = int(ss[0])
                p = int(ss[1])
                r += asd * (a**p)
            else:
                ss = s[:-1]
                if '.' in ss:
                    asdf = ss.split('.')
                    it, up = int(asdf[0]),int(asdf[1])
                    asd = it
                    asd += up * ((0.1)**len(asdf[1]))
                else:
                    if ss =='':
                        asd = 1
                    else:
                        asd = int(ss)
                r += asd*a

    return r

def get_function():
    s = input("f(x) = ")
    return s.split(' ')

def main():
    l = get_function()
    at,bt = input("적분범위? ").split(' ')
    a,b = int(at),int(bt)
    s = 0; t=(b-a)*A
    for i in range(int(1/A)):
        s += f(a+(t*i),l)*t
    print('적분값 : ',s)

if __name__=='__main__':
    main()

 

 

사실 코드를 잘 읽어보면 결점이 많이 보일 것이다. 
이 잘못 짜여진 코드는, 무려 각 항 사이에 덧뺄셈 기호를 입력받지 않는다!!!!!!!!!!!!!!!!!
물론, 다항함수의 경우 앞에 -1 또는 -를 붙이는 방식으로 -기호를 강제로 넣어줄 수는 있지만, 삼각함수는 그런 거 없다!
또한, 삼각함수의 경우 무려 삼각함수에 들어가는 식은 반드시 x에 관한 일차식, 그것도 무려 상수항이 없는 일차식이어야한다!
이 얼마나 대단한(가리가 단한) 코드인가. 하지만, 이번 코드에선 "삼각함수도 넣어줬다"라는 정도만으로도 많은 발전이라 생각하도록 하자. 
그래도 x의 계수에 유리수도 올 수 있게 해주었지 않는가. 

아, 참고로, 이 코드를 작성한 내가 아직 고등학교 수준의 미적분밖에 배우지 못했으므로 당연히 저 코드도 고등학교 미적분에서 나오는 sin cos tan sec csc cot밖에 모른다.

다시말해 이런 해괴망측한 앞에 arc가 붙는건 모른단 말이다. 

 

아무튼 그래서 이 코드가 계산을 잘 하는지 궁금할 것이다. 

 

일단 예시로, f(x) = cos(3.14 * x) + 3x + 4x² 에 대해 3부터 1까지의 적분값을 계산시킨 결과다. 이 값과 Wolframalpha의 계산 값을 비교해보도록 하자. 

부정적분에 함수 그래프까지 그려준다니.... 그는 신이야!

꽤 비슷한 값을 도출한다!

그럼 한번 다른 함수도 한번 시도해보도록 하자.

f(x) = sin(x) + tan(2x) + cos(5x) + 2x^5에 대한 1부터 7까지의 적분값을 계산한 결과다. 과연 wolframalpha는 어떻게 계산했을까. 

 

INTEGRAL DOES NOT CONVERGE

아마 tan(2x)때문일 것이다. 1부터 7까지 2x의 값을 tan에 넣으면 그 사이에만 발산하는 값이 4개는 나오기 때문이겠지....
tan(2x)를 빼고 다시 해보자. 

우선, 내가 짠 코드는 이런 결과를 보였다. 

그리고 wolframalpha또한 비슷.........한 결과를 도출했다. 

 

아무튼 난 코드 제대로 짰다. 
잘 계산 하니 상관 없을 것이다. 그래. 상관 없어야지.