파이썬을 이용한 수식 계산

수식 계산?

  • 모든 사람들이 문제점을 이해합니다.

  • 많은 중요 개념들은 다음과 같은 것을 포함합니다.

    • 변수

    • 수학 연산

    • 객체

    • 텍스트와 출력

수식 계산의 예

수직 운동하는 공의 높이

\[y(t) = v_0 t - \frac{1}{2}gt^2\]

여기서

  • \(y\)는 시간 \(t\)에 관한 높이

  • \(v_0\)\(t=0\)에서의 처음 속도

  • \(g\)는 중력가속도

우리가 해야할 일은 \(v_0\), \(g\)\(t\)가 주어졌을 때 공의 높이 \(y\)를 계산하는 겁니다.

첫번째 프로그래밍

처음 속도 \(v_0=5\)이고 중력가속도는 \(g=9.81\), 시간은 \(t=0.6\)로 주어질 때 \(y(t) = v_0t- \frac{1}{2}gt^2\)를 구하시오.

\[y = 5\cdot 0.6 - \frac{1}{2}\cdot 9.81 \cdot 0.6^2\]

파이썬 프로그래밍은 다음과 같습니다.

In [1]: print(5 * 0.6 - 0.5 * 9.81 * 0.6 ** 2)
1.2342

적분 예제

다음은 손으로 적분값을 구할 수 없는 적분형태입니다.

\[\int_{-\infty}^1 e^{-x^2}dx{\thinspace .}\]

하지만 프로그래밍을 이용하면 근사적으로 어떤 범위 적분도 할 수 있습니다.

from numpy import *

def integrate(f, a, b, n=100):
  """
  사다리꼴 메소드를 이용하여 n개의 구간에서 a 부터 b 까지 함수 f를 적분합니다.
  """
  x = linspace(a, b, n+1)    # 구간의 좌표들
  h = x[1] - x[0]            # 구간의 길이
  I = h * (sum(f(x)) - 0.5 * (f(a) + f(b)))
  return I

# 피적분함수 정의
def my_function(x):
  return exp(-x**2)

minus_infinity = -20  # 음의 무한대 근사값
I = integrate(my_function, minus_infinity, 1, n=1000)
print('적분값: ', I)

이 프로그램을 이용해서 구간의 갯수 \(n=10^6\)일 때 오차가 \(10^{-12}\) 이내로 순식간에 적분을 할 수 있습니다.

파이썬 기본 구문

변수

변수를 이용하면 프로그램을 이해하는 것이 훨씬 편리합니다.

수학에서도 다음과 같이 변수들을 사용하는 것을 알 수 있습니다.

\[v_0=5,\quad g=9.81,\quad t=0.6,\quad y = v_0t -\frac{1}{2}gt^2\]

위의 식을 파이썬으로 변경하면 다음과 같습니다.

In [2]: v0 = 5
   ...: g = 9.81
   ...: t = 0.6
   ...: y = v0 * t - 0.5 * g * t ** 2
   ...: print(y)
   ...: 
1.2342

변수들을 도입해서 여러 줄에 나누어서 입력을 했습니다. 위에서 계산한 것과 똑같은 결과가 나오는 것을 볼 수 있습니다.

변수 이름 규칙

  • 영문자 및 유니코드(한글) 및 밑줄 _과 숫자 사용가능합니다.

  • 숫자는 처음에 올 수 없습니다.

  • 대소문자를 다르게 인식합니다. (예를 들면, aA는 다른 변수입니다.)

아래는 이해할 수 있는 변수 이름을 사용한 예입니다.

initial_velocity = 5
accel_of_gravity = 9.81
TIME = 0.6
VerticalPositionOfBall = initial_velocity*TIME - \
                         0.5*accel_of_gravity*TIME**2
print VerticalPositionOfBall

(주의: 위에서 줄의 맨 끝에 있는 백슬래시(\)는 다음 줄과 이어지는 것을 나타낼 때 사용합니다.)

파이썬 예약어

파이썬이 미리 예약해둔 문자열은 변수로 사용할 수 없습니다. 다음은 파이썬 예약어들입니다.

False      class      finally    is         return
None       continue   for        lambda     try
True       def        from       nonlocal   while
and        del        global     not        with
as         elif       if         or         yield
assert     else       import     pass
break      except     in         raise

주석

다음은 주석(comment)이 들어간 프로그램입니다.

# program for computing the height of a ball
# in vertical motion
v0 = 5    # initial velocity
g = 9.81  # acceleration of gravity
t = 0.6   # time
y = v0*t - 0.5*g*t**2  # vertical position
print y

주의:

  • 주석 기호 # 뒤에 있는 문자들은 모두 무시됩니다.

  • 주석은 코드가 무엇을 의미하는 지 설명할 때 사용합니다.

형식화된 문자열

파이썬에서 형식화된 문자열을 이용하면 계산된 숫자의 출력을 원하는 모양으로 변경할 수 있습니다.

형식화된 문자열이란 문자열 안에 중괄호 {}를 포함하는 문자열을 말합니다. 형식화된 문자열과 format() 메소드를 이용해서 중괄호에 들어가는 것을 편리하게 원하는 형식으로 변경할 수 있습니다.

In [3]: fmt_str = '이름은 {} 이고 나이는 {}세 입니다.'
   ...: fmt_str.format('지원', 20)
   ...: 
Out[3]: '이름은 지원 이고 나이는 20세 입니다.'

fmt_str.format('지원', 20)도 문자열입니다. 중괄호 안에 콜론 뒤에 출력 숫자의 형식을 지정할 수도 있습니다.

In [4]: t = 0.6;  y = 1.2342
   ...: print('t={:g} 초일 때, y는 {:.2f} 미터입니다.'.format(t, y))
   ...: 
t=0.6 초일 때, y는 1.23 미터입니다.

형식 문자

g         간결한 실수형
f         실수형 (-34.674)
10.3f     길이 10이고 소수점 아래 3자리
.3f       소수점 아래 3자리
e or E    과학 표현식 (1.42e-02 또는 1.42E-02)
9.2e      길이 9이고 소수점 아래 2자리
d         정수
5d        길이 5 정수 표현
s         문자열
-20s      길이가 20 왼쪽 정렬 문자열

(자세한 것은 파이썬 문서를 참조하세요)

세겹 따옴표 문자열

세겹 문자열 """을 이용하면 여러 줄에 걸친 출력을 할 수 있습니다.

In [5]: v0 = 5
   ...: g = 9.81
   ...: t = 0.6
   ...: y = v0*t - 0.5*g*t**2
   ...: print("""
   ...: 시각 t={:f} 초, 처음 속도 v0={:.3E} m/s
   ...: 일 때 높이는 {:.2f} 미터입니다.
   ...: """.format(t, v0, y))
   ...: 

시각 t=0.600000 초, 처음 속도 v0=5.000E+00 m/s
일 때 높이는 1.23 미터입니다.

프로그램은 문장으로 구성

a = 1      # 첫번째 문장 (할당 문장)
b = 2      # 두번째 문장 (할당 문장)
c = a + b  # 세번째 문장 (할당 문장)
print(c)   # 네번째 문장 (출력 문장)

일반적으로 한 줄에 한 문장을 사용합니다. 여러 문장을 한 줄에 사용하려면 세미콜론을 사용하여 구분합니다.

a = 1;  b = 2;  c = a + b;  print(c)

할당문

할당 문장은 등호 오른쪽이 먼저 평가되어 왼쪽 변수에 할당됩니다.

In [6]: myvar = 10
   ...: myvar = 3*myvar   # = 30
   ...: myvar
   ...: 
Out[6]: 30

문법

프로그램은 정확한 문법을 지켜야합니다.

다음 프로그램은 2개의 오류를 가지고 있습니다.

myvar = 5.2
prinnt(Myvar)

2개 오류가 있지만 첫번째 오류만 보고가 되며 멈춥니다.

공백

파이썬 프로그램에서 공백은 상황에 따라 다르게 적용이 됩니다.

다음 문장은 모두 같은 것을 의미합니다.(공백은 문제가 되지 않습니다.)

v0=3
v0  =  3
v0=   3
v0 = 3

다음은 공백이 문제가 됩니다.

counter = 1
while counter <= 4:
    counter = counter + 1   # 옳은 문법 (4개의 공백)

while counter <= 4:
counter = counter + 1       # 잘못된 문법

입력 및 출력

In [7]: v0 = 3;  g = 9.81;  t = 0.6
   ...: position = v0 * t - 0.5 * g * t * t
   ...: velocity = v0 - g * t
   ...: print('position:', position, 'velocity:', velocity)
   ...: 
position: 0.034199999999999786 velocity: -2.886
  • 입력: v0, g, t

  • 출력: position, velocity

온도 단위 변환

섭씨 온도 \(C\) 일 때 화씨 온도 \(F\)를 구하시오.

\[F = \frac{9}{5}C + 32\]

프로그램:

In [8]: C = 21
   ...: F = (9 / 5) * C + 32
   ...: print(F)
   ...: 
69.80000000000001

모든 것은 객체

변수는 객체를 참조합니다.

In [9]: a = 5       # a 는 정수 (int) 객체
   ...: b = 9       # b 는 정수 (int) 객체
   ...: c = 9.0     # c 는 실수 (float) 객체
   ...: d = b/a     # d 는 정수/정수 => 실수 객체
   ...: e = c/a     # e 는 실수/정수 => 실수 객체
   ...: s = 'b/a={:g}'.format(b / a)  # s 는 문자열 객체
   ...: print(d, e, s)
   ...: 
1.8 1.8 b/a=1.8

객체 사이에 형변환이 가능합니다.

In [10]: a = 3              # a 는 int
   ....: b = float(a)       # b 는 float 3.0
   ....: c = 3.9            # c 는 float
   ....: d = int(c)         # d 는 int 3
   ....: d = round(c)       # d 는 float 4.0
   ....: d = int(round(c))  # d 는 int 4
   ....: d = str(c)         # d 는 str '3.9'
   ....: e = '-4.2'         # e 는 str
   ....: f = float(e)       # f 는 float -4.2
   ....: 

수식 연산 순위

  • 예제: \(\frac{5}{9} + 2a^4/2\)는 파이썬으로 5/9 + 2*a**4/2

  • 사칙연산 우선 순위는 수학 연산과 동일합니다.

  • r1 = 5/9

  • r2 = a**4

  • r3 = 2*r2

  • r4 = r3/2

  • r5 = r1 + r4

  • 소괄호가 가장 먼저 계산됩니다.: (5/9) + (2*(a**4))/2

기본 수학 함수 모듈 math

  • \(\sin x\), \(\cos x\), \(\ln x\) 계산?

  • 파이썬 math 모듈

  • 파이썬 필요한 유용한 기능들은 모듈을 이용할 수 있습니다. 반드시 import를 해야 합니다.

\(\sqrt{2}\)math 모듈의 sqrt 함수를 이용해서 구합니다.

In [11]: import math
   ....: r = math.sqrt(2)
   ....: # or
   ....: from math import sqrt
   ....: r = sqrt(2)
   ....: # or
   ....: from math import *   # import everything in math
   ....: r = sqrt(2)
   ....: 

math 모듈을 사용한 다른 예제

\(x=1.2\) 일 때 다음을 계산합니다.

\[Q = \sin x\cos x + 4\ln x\]
In [12]: import math
   ....: x = 1.2
   ....: Q = math.sin(x) * math.cos(x) + 4 * math.log(x)   # log 는 자연로그 ln (밑이 e)
   ....: print(Q)
   ....: 
1.0670178174513938

오차

다음을 계산합니다. \(1/49\cdot 49\), \(1/51\cdot 51\):

In [13]: v1 = 1/49.0*49
   ....: v2 = 1/51.0*51
   ....: print('{:.16f} {:.16f}'.format(v1, v2))
   ....: 
0.9999999999999999 1.0000000000000000

주의:

  • 컴퓨터에서 대부분의 실수는 근사값입니다.(소수점 아래 17 자리)

  • 1/49, 1/51 정확한 값을 갖지 않습니다. 일반적으로 오차는 \(10^{-16}\) 입니다.

  • 이러한 오차는 다른 계산할 때 전파될 수 있습니다.

근사값 계산 예제

다음 코드를 실행하면 무엇이 출력되나요?

a = 1; b = 2;
computed = a + b
expected = 3
correct = computed == expected
print('Correct:', correct)

만일 a = 0.1, b = 0.2로 변경하면 무엇일 출력될 것 같은가요? 출력 결과에 대해서 이야기해 보세요.

풀이

In [14]: a = 0.1
   ....: b = 0.2
   ....: expected = 0.3
   ....: a + b == expected
   ....: 
Out[14]: False
In [15]: print('{:.17f}\n{:.17f}\n{:.17f}\n{:.17f}'.format(0.1, 0.2, 0.1 + 0.2, 0.3))
0.10000000000000001
0.20000000000000001
0.30000000000000004
0.29999999999999999

다른 수학 함수 예제

\(\sinh x\) 함수는 다음과 같이 정의됩니다.

\[\sinh (x) = \frac{1}{2}\left(e^{x} - e^{-x}\right)\]

3가지 방법으로 계산이 가능합니다.

  1. math.sinh

  2. math.exp을 조합

  3. math.e을 이용

In [16]: import math
   ....: 
   ....: x = 2 * pi
   ....: r1 = math.sinh(x)
   ....: r2 = 0.5 * (math.exp(x) - math.exp(-x))
   ....: r3 = 0.5 * (math.e ** x - math.e ** (-x))
   ....: print('r1 = {:.16f},\nr2 = {:.16f},\nr3 = {:.16f}'.format(r1, r2, r3))
   ....: 
r1 = 267.7448940410164369,
r2 = 267.7448940410164369,
r3 = 267.7448940410163232

결과: r1: \(267.744894041016\underline{4369}\) r2: \(267.744894041016\underline{4369}\) r3: \(267.744894041016\underline{3232}\)

복소수

복소수 \(2 + 3i\) 는 파이썬에서는 2 + 3j로 표현합니다.

In [17]: w = 2 + 3j
   ....: w
   ....: 
Out[17]: (2+3j)

complex() 함수를 이용할 수도 있습니다.

In [18]: a = -2
   ....: b = 0.5
   ....: s = complex(a, b)  # complex() 이용
   ....: s
   ....: 
Out[18]: (-2+0.5j)

복소수 곱

In [19]: s * w # complex*complex
Out[19]: (-5.5-5j)

복소수 나눗셈

In [20]: s / w # complex/complex
Out[20]: (-0.1923076923076923+0.5384615384615385j)

복소수의 실수, 허수 성분

In [21]: s.real
   ....: s.imag
   ....: 
Out[21]: 0.5

심볼릭 계산

  • 수치 계산: 수를 가지고 계산

  • 심볼릭 계산: 문자 공식 계산

In [22]: import sympy
   ....: 
   ....: t, v0, g = sympy.symbols('t v0 g')
   ....: y = v0*t - sympy.Rational(1, 2) * g * t ** 2
   ....: dydt = sympy.diff(y, t)                     # 한 번 미분
   ....: dydt
   ....: 
Out[22]: -g*t + v0
In [23]: print('가속도:', sympy.diff(y, t, t))  # 2번 미분
가속도: -g
In [24]: y2 = sympy.integrate(dydt, t)
   ....: y2
   ....: 
Out[24]: -g*t**2/2 + t*v0

더 많은 수학 심볼릭 계산

방정식을 풀 수 있습니다.

In [25]: y = v0*t - sympy.Rational(1, 2) * g * t ** 2
   ....: roots = sympy.solve(y, t)    # 방정식 y = 0를 t에 대해서 풉니다.
   ....: roots
   ....: 
Out[25]: [0, 2*v0/g]

공식을 이용하여 간단히 합니다.

In [26]: x, y = sympy.symbols('x y')
   ....: f = -sympy.sin(x) * sympy.sin(y) + sympy.cos(x) * sympy.cos(y)
   ....: sympy.simplify(f)
   ....: 
Out[26]: cos(x + y)

전개를 합니다.

In [27]: sympy.expand(sympy.sin(x + y), trig=True)  # trigonometric hint
Out[27]: sin(x)*cos(y) + sin(y)*cos(x)

연습문제

  1. 1 + 3을 계산하세요.

  2. 안녕하세요. 파이썬!을 출력하는 프로그램을 작성하세요.

  3. 백만(\(10^6\))초는 몇 년, 몇 일인지 계산하는 프로그램을 작성하세요.

  4. 미터를 인치, 피트로 변경하는 프로그램을 작성하세요. 작성한 프로그램을 이용해서 640미터를 인치와 피트로 변경하세요. 1인치는 2.54cm로 1피트는 12인치로 계산하세요.

  5. 이자율이 \(p\)이고 원금 \(A\) 일 때 \(n\) 년후의 받을 돈은 다음과 같습니다.

    \[A\left( 1 + p\right)^n\]

    이자율 \(p=0.02\)일 때, 1000만원을 10년 동안 예금했을 때 받는 돈을 구하세요.

  6. 다음 프로그램에서 에러가 발생한 곳을 찾고, 올바르게 고쳐보세요.

    x = 1
    print('sin({:g}) = {:g}'.format(x, sin(x)))
    
  7. 다음 프로그램 코드를 파일 areas.py로 저장하고 실행해보세요.

    import math
    
    h = 5.0 # 높이
    b = 2.0 # 밑변
    r = 1.5 # 반지름
    
    area_parallelogram = h * b
    print('평행사변형의 넓이는 {:.3f}'.format(area_parallelogram))
    
    area_square = b ** 2
    print('정사각형의 넓이는 {:g}'.format(area_square))
    
    area_circle = math.pi * r ** 2
    print('원의 넓이는 {:.3f}'.format(area_circle))
    
    volume_cone = 1.0 / 3 * math.pi * r ** 2 * h
    print('원뿔의 부피는 {:.3f}'.format(volume_cone))
    
  8. 다음을 실행해보고 에러가 발생하면 에러가 발생한 이유를 말하고, 올바르게 고쳐서 작동하게 만드세요.

    1. \(x= \pi/4\) 일 때, \(\sin^2(x) + \cos^2(x) = 1\) 성립하는지 보이는 프로그램입니다.

      import math
      x = pi / 4
      1_val = sin^2(x) + cos^2(x)
      print(1_VAL)
      
    2. 등가속도 운동의 거리를 구하는 식입니다.

      v0 = 3 m/s
      t = 1 s
      a = 2 m/s**2
      s = v0*t + 1/2 a * t ** 2
      print(s)
      
    3. \(a = 3.3\), \(b = 5.3\) 일 때, 다음 항등식이 성립하는지 보이는 프로그램입니다.

      \[\begin{split}(a + b)^2 = a^2 + 2ab + b^2 \\ (a − b)^2 = a^2 − 2ab + b^2\end{split}\]
      a = 3,3 b = 5,3
      a2 = a**2
      b2 = b**2
      eq1_sum = a2 + 2ab + b2
      eq2_sum = a2 - 2ab + b2
      eq1_pow = (a + b)**2
      eq2_pow = (a - b)**2
      print('First equation: {:g} = {:g}'.format(eq1_sum, eq1_pow))
      print('Second equation: {:g} = {:g}'.format(eq2_pow, eq2_pow))
      
  9. 다음과 같은 가우스 함수에서 \(\mu = 0, \sigma = 2\), \(x = 1\)일 때 함수값을 구하는 프로그램을 작성하세요.

    \[f(x) = \frac{1}{\sigma \sqrt{2\pi}} e^{-(x - \mu)^2 / (2 \sigma^2)}\]
  10. 다음 프로그램이 작동하지 않는 이유를 설명하세요.

    C = A + B
    A = 3
    B = 2
    print(C)
    
  11. 다음 문장들을 실행해보고 에러가 나면 이유를 말하고 고쳐서 실행해보세요.

    1. 1a = 2

    2. a1 = b

    3. x = 2

    4. y = X + 4 # is it 6?

    5. from Math import tan

    6. print(tan(pi))

    7. pi = "3.14159’

    8. print(tan(pi))

    9. c = 4**3**2**3

    10. _ = ((c-78564)/c + 32))

    11. discount = 12%

    12. AMOUNT = 120.-

    13. amount = 120$

    14. address = hpl@simula.no

    15. and = duck

    16. class = ’INF1100, gr 2"

    17. continue_ = x > 0

    18. rev = fox = True

    19. Norwegian = [’a human language’]

    20. true = fox is rev in Norwegian

  12. 다음은 2차 방정식

    \[ax^2 + bx + c =0\]

    의 해

    \[x_1 = \frac{-b + \sqrt{b^2 - 4ac}}{2a}, \quad x_2 = \frac{-b - \sqrt{b^2 - 4ac}}{2a}\]

    \(a=2, b=1, c=2\) 일 때, 구하는 프로그램입니다. 잘못된 곳을 찾으세요.

    a = 2; b = 1; c = 2
    from math import sqrt
    q = sqrt(b*b - 4*a*c)
    x1 = (-b + q)/2*a
    x2 = (-b - q)/2*a
    print(x1, x2)
    

연습문제 풀이