Processing math: 84%

2020년 12월 16일 수요일

Numeric Analysis 1 - 기초

Numeric Analysis 1 - 기초

Numeric Analysis

In [1]:
from math import *

Overflow

수치 값이 대략 10308 이 넘으면 오버플로우(overflow) 에러가 발생한다.

In [2]:
1.79e308
Out[2]:
1.79e+308

위의 값이 컴퓨터가 수치적으로 허용하는 최대값이다. 더 큰 값은 무한대로 취급한다.

In [3]:
1.80e308
Out[3]:
inf

Underflow

In [4]:
1.23e-308
Out[4]:
1.23e-308

수치 값이 대략 10308 보다 작으면 언더플로우(underflow)가 되어 0으로 처리된다.

In [5]:
1.0e-324
Out[5]:
0.0

Roundoff

반올림(rounding)에 의하여 수치적인 오차가 생긴다.

In [6]:
round( pi, 2 )
Out[6]:
3.14

컴퓨터는 중간 계산 과정에서는 반올림을 하지 않으므로 큰 문제는 없다.

Truncation error

유효 숫자의 갯수가 16자리를 초과하면, 그 뒷자리의 숫자는 잘려나간다. 이로 인하여 수치적 오차가 발생한다.

In [7]:
1.0e10 + 1
Out[7]:
10000000001.0
In [8]:
1.0e15 + 1
Out[8]:
1000000000000001.0

지금까지는 문제가 없다. 하지만 다음의 경우

In [9]:
1.0e16 + 1
Out[9]:
1e+16

아주 큰 숫자와 아주 작은 숫자는 덧셈이 불가능하게 되는 오류가 생기는 것이다.

Solution of Equations by Iteration

to find solutions of a single equation numerically

f(x)=0

Fixed-Point Iteration

After transforming into the form x=g(x)

We start with a guessed value x0, and compute

x1=g(x0), x2=g(x1),

It is also called the method of successive substitution.

[ Example 1 ] Find a solution of f(x)=x23x+1=0

Rewrite the equation as x=13(x2+1)

In [10]:
# initial guess
x = 1  

for i in range(10) :
    xnew = 1/3 *(x**2+1)
    x = xnew
    print("%9.5f" % x )
  0.66667
  0.48148
  0.41061
  0.38953
  0.38391
  0.38246
  0.38209
  0.38200
  0.38197
  0.38197
In [11]:
# initial guess
x = 3  

for i in range(10) :
    xnew = 1/3 *(x**2+1)
    x = xnew
    print("%9.5f" % x )
  3.33333
  4.03704
  5.76589
 11.41516
 43.76863
638.89754
136063.68691
6171108965.24800
12694195286988072960.00000
53714197994730060054154112125389242368.00000

image.png

x=13(x2+1)

Newton’s Method for Solving Equations ƒ(x) = 0

image.png

xn+1=xnf(xn)f(xn)

[ Example 4 ] Find a solution of 2sinx=x

In [12]:
from scipy.optimize import newton

def func(x):
    return 2*sin(x)-x     # f(x) = 0


xsol = newton( func, 2 )  # newton(함수이름,초기값)
print("%9.5f" % xsol)
  1.89549

소스 코드

In [13]:
def func(x) :
    return 2*sin(x)-x     # f(x) = 0
  
def newton( x0 ) :
    x = x0
    dx = x * 1e-5
    for i in range(100) :                          # maximum 100 iterations
        f = func( x )
        if abs( f ) < 1e-5 :  break
        dfdx = ( func( x+dx ) - f ) / dx 
        x += - f / dfdx
    return  x
  

xsol = newton( 2 )
print("%9.5f" % xsol )
  1.89549

Interpolation (내삽, 보간)

Linear interpolation

interpolation by the straight line through (x0,f0), (x1,f1)

image.png

[ Example 1 ] Linear Lagrange Interpolation

For f(x)=lnx, compute ln9.2 from ln9.0=2.1972 and ln9.5=2.2513

In [14]:
def interpol( x, x0,f0, x1,f1 ) :
    p = (x-x1)/(x0-x1)*f0 + (x-x0)/(x1-x0)*f1
    return p


p = interpol( 9.2,  9.0, 2.1972,  9.5, 2.2513 )
print("approx = %9.5f" % p )

print("ln 9.2 = %9.5f  (exact value)" % log(9.2) )
approx =   2.21884
ln 9.2 =   2.21920  (exact value)

Numeric Integration

Rectangular rule

image.png

Piecewise constant approximation of f(x)

image.png

Trapezoidal rule

image.png

Piecewise linear approximation of f(x)

image.png

h=ban

[ Example 1 ] Trapezoidal Rule

Evaluate J=10ex2dx

In [15]:
def f(x) :
    return exp(-x**2)

n = 10
a = 0
b = 1
h = (b-a)/n

sum = f(a)/2 + f(b)/2
for i in range(1,n) :
    xi = a + i*h
    sum += f(xi)

J = h * sum
print("%9.6f" % J )
 0.746211

Scipy 라이브러리를 사용하여 정확한 적분값을 구해보면

In [16]:
from scipy.integrate import quad

J, err = quad( f, 0, 1 )
print("%9.6f" % J )
 0.746824

Simpson’s Rule

image.png

Piecewise quadratic approximation of f(x)

인접한 3개의 점들을 연결하는 2차 곡선 (포물선)을 만들고, 이러한 2차 곡선들을 적분함으로써 함수 f(x)의 정적분을 계산한다.

1차 곡선(직선)으로 가정하는 사다리꼴 공식(trapezoidal rule)보다 정확도가 더 높다.

image.png

h=ba2m

where 2m is the number of subintervals, n=2m

image.png

[ Example 3 ] Simpson’s Rule

Evaluate J=10ex2dx with n=2m=10

In [17]:
def f(x) :
    return exp(-x**2)

n = 10
a = 0
b = 1
h = (b-a)/n

s0 = f(a) + f(b)
s1 = 0
s2 = 0
for i in range(1,n) :
    xi = a + i*h
    if i%2 == 1 :    # 홀수
        s1 += f(xi)
    else :           # 짝수
        s2 += f(xi)

J = h/3 *( s0 + 4*s1 + 2*s2 ) 
print("%9.6f" % J )
 0.746825

Only the last digit differs from the exact value of 0.746824

Adaptive Integration

스텝의 크기 h 를 구간 마다 가변적으로 적용하여 적분 값의 오차를 줄이는 방법

Gauss Integration Formula (Gauss Quadrature)

image.png

미리 정해진 노드 tj 와 계수 (또는 가중치) Aj 를 이용하여 적분 값을 계산한다.

x=12[a(t1)+b(t+1)]

변수 변환에 의하여

baf(x)dx=ba211f[x(t)]dtba2nj=1Ajfj

image.png

[ Example 7 ] Gauss Integration Formula with n=3

Evaluate J=10ex2dx

In [18]:
def f(x) :
    return exp(-x**2)

n = 3
t = [ -0.7745966692, 0, 0.7745966692]
A = [ 0.5555555556, 0.8888888889, 0.5555555556]

a = 0
b = 1

sum = 0
for i in range(n) :
    xi = 1/2*(-a*(t[i]-1) + b*(t[i]+1) )
    sum += A[i] * f(xi)

J = (b-a)/2 * sum
print("%9.6f" % J )
 0.746815

With n=4

In [19]:
def f(x) :
    return exp(-x**2)

n = 4
t = [ -0.8611363116, -0.3399810436, 0.3399810436, 0.8611363116]
A = [ 0.3478548451, 0.6521451549, 0.6521451549, 0.3478548451]

a = 0
b = 1

sum = 0
for i in range(n) :
    xi = 1/2*(-a*(t[i]-1) + b*(t[i]+1) )
    sum += A[i] * f(xi)

J = (b-a)/2 * sum
print("%9.6f" % J )
 0.746824

The result is almost the same with the exact value of 0.746824

Numeric Differentiation

Differentiation is defined by

f(x)=lim

Numeric differentiation is approximated by the forward difference

f'(x) \approx \frac {f(x+h)-f(x)} h \qquad \,\,\, \text {with a small } h

or given by the backward difference

f'(x) \approx \frac {f(x)-f(x-h)} h \qquad \,\,\,

The central difference gives more accure approximation

f'(x) \approx \frac {f(x+h)-f(x-h)} {2h}

[ Example ] find the value of the derivative of e^{-x^2} at x=1.

In [20]:
def f(x) :
    return exp(-x**2)

def dfdx(x) :
    return -2*x*exp(-x**2)

x = 1
h = 0.01

# the forward difference
fp = ( f(x+h) - f(x) )/h
print("the forward  difference  f' = %9.6f" % fp )

# the backward difference
fp = ( f(x) - f(x-h) )/h
print("the backward difference  f' = %9.6f" % fp )

# the central difference
fp = ( f(x+h) - f(x-h) )/(2*h)
print("the central  difference  f' = %9.6f" % fp )

# the exact value
print()
print("the exact value          f' = %9.6f" % dfdx(x) )
the forward  difference  f' = -0.732056
the backward difference  f' = -0.739413
the central  difference  f' = -0.735734

the exact value          f' = -0.735759

The second-order derivative

The forward difference

f''(x) \approx \frac {f(x)-2f(x+h)+f(x+2h)} {h^2}

The backward difference

f''(x) \approx \frac {f(x-2h)-2f(x-h)+f(x)} {h^2}

The central difference

f''(x) \approx \frac {f(x-h)-2f(x)+f(x+h)} {h^2}

댓글 없음:

댓글 쓰기

Numeric Analysis 4 - Numeric Linear Algebra

Numeric Analysis 4 - Numeric Linear Algebra Numeric Linear Algebra ¶ ...