[Python]수학적 기초 with NumPy

NumPy 기초

NumPy의 배열

import numpy as np
arr0 = [1.0, 2.0, 3.0]
print(arr0)
print(type(arr0))

arr1 = np.array([1.0, 2.0, 3.0]) # list -> ndarray
print(arr1)
print(type(arr1))

arr2 = list(arr1) # ndarray -> list
print(arr2)
print(type(arr2))
[1.0, 2.0, 3.0]
<class 'list'>
[1. 2. 3.]
<class 'numpy.ndarray'>
[1.0, 2.0, 3.0]
<class 'list'>
import numpy as np
arr0 = [1.0, 2.0, 3.0]
arr1 = np.array(arr0) # list->ndarray
arr2 = np.arange(0, 10, 2) # 2씩 띄어서 배열 생성
arr3 = np.zeros(3)
arr4 = np.ones(3)
arr5 = np.empty(3)
print(arr0, arr1, arr2, arr3, arr4, arr5)
[1.0, 2.0, 3.0] [1. 2. 3.] [0 2 4 6 8] [0. 0. 0.] [1. 1. 1.] [1. 1. 1.]

NumPy의 행렬

import numpy as np
arr0 = np.zeros((2,2)) # (N,N)
print(arr0)
arr1 = np.array([[0,1],[2,3]]) # [ [], [].. ]
print(arr1)
[[0. 0.]
 [0. 0.]]
[[0 1]
 [2 3]]

간단한 선형 시스템

  • 4a + 3b = 23

    3a + 2b = 16

import numpy as np
a = np.array([[4,3], [3,2]])
b = np.array([23, 16])
x = np.linalg.solve(a, b)
print(x) # a, b 값
[2. 5.]


수치적 오차 확인 : 자연로그

자연로그와 테일러급수의 오차확인

자연로그는 기호 e로 표기되는 특정 상수를 밑으로 하는 로그

급수는 부분합의 극한을 의미 -> 무한급수, 무한합이라고도 한다.

테일러가 만들었기에 테일러급수라 한다.

테일러 전개식

\[ln(1+x) = x^1 - \frac{x^2}{2} + \frac{x^3}{3} - \frac{x^4}{4} + ...\] \[ln(2) = 1^1 - \frac{1}{2} + \frac{1}{3} - \frac{1}{4} + ...\]
import numpy as np
def NatLog(x, loop): # 이 함수는 테일러 전개식과 같다.
    ans=0
    for i in range(1,loop+1):
        if i%2==0:
            ans -= pow(x,i)/i
        else:
            ans += pow(x,i)/i
    return ans
# ln(2)로 오차 테스트 -> 무한으로 갈수록 정확한 극한값이 나온다.
print("ln(2) = "+str(NatLog(1,8)))
print("ln(2) = "+str(NatLog(1,80)))
print("ln(2) = "+str(NatLog(1,800)))
print("ln(2) = "+str(np.log(2))) # 정확한 값(비교를 위해 출력)
ln(2) = 0.6345238095238095
ln(2) = 0.6869362400091404
ln(2) = 0.6925225711846422
ln(2) = 0.6931471805599453

자연로그와 테일러급수의 오차확인(개선)

테일러 전개식(개선)

\[ln(\frac{1+x}{1-x}) = 2(\frac{x^1}{1} + \frac{x^3}{3} - \frac{x^5}{5} + ...)\] \[ln(2) = 2(\frac{3^{-1}}{1} + \frac{3^{-3}}{3} - \frac{3^{-5}}{5} + ...)\]
  • 참고 : x=3-1
def NatLogImproved(x,loop): # 테일러 식과 동일
    ans = 0
    for idx, i in enumerate(range(1,loop+1,2)):
        ans+=pow(x,i)/i
    return ans*2.0
print("ln(2) = "+str(NatLogImproved(1/3,8)))
print("ln(2) = "+str(NatLogImproved(1/3,80)))
print("ln(2) = "+str(np.log(2))) # 정확한 값
ln(2) = 0.6931347573322881
ln(2) = 0.6931471805599451
ln(2) = 0.6931471805599453


축소 곱셈법과 호너 알고리즘

  • 축소 곱셈법은 계속 x를 밖으로 꺼내가는게 축소 곱셈법이다.

  • 호너 알고리즘은 이 축소 곱셈법으로 구한 식을 계산하는 알고리즘이다.

  • 호너 알고리즘을 조립제법 이라고도 한다.

  • 호너 알고리즘을 통해 다항식을 축소 할 수 있다.

축소 곱셈법

import numpy as np
import sympy as sp

# f(x) = 1 + 2*x + 3*x**2 + 4*x**3 + 5*x**4
f = [1,2,3,4,5] # x빼고 나열(상수만)
f2 = [5,3,-7,2] # 교재 다항식
def nested(a):
    x=sp.symbols("x")
    f = a[-1] # end index : len(a)-1
    for i in range(len(a)-2, -1, -1): # pseudo : i=n-1 to 0
        f = a[i] + (f*x)
    return f

print(nested(f))
print(nested(f2))
x*(x*(x*(5*x + 4) + 3) + 2) + 1
x*(x*(2*x - 7) + 3) + 5

호너 알고리즘

def horner(a,r):
    # a가 조립제법의 x앞 숫자들 배열이고, b가 조립제법의 연산된 값들이다
    b = a[-1] # end index : len(a)-1
    for i in range(len(a)-2, -1, -1): # pseudo : i=n-1 to 0
        b = a[i] + (r*b)
    return b

# f(x) = 1*x**4 - 4*x**3 + 7*x**2 - 5*x - 2
f = [1,-4,7,-5,-2] # x빼고 나열
f.reverse() # 함수를 x차수가 오름차순인 형태의 f(x)식 전용으로 만들어서 reverse() 했음.
print(f)
r = 3
print(horner(f, r)) # f(3) 적용
print(horner(f, 2))# f(2) 적용 => x=2는 근이라서 f(2)=0 출력
[-2, -5, 7, -4, 1]
19
0

댓글남기기