Prikaz brojeva u računalu¶
FP-brojevi u IEEE strandardu prikazuju mogu biti jednostruke i dvostruke preciznosti. Maksimalni i minimalni prikazivi broj u dvosturkoj preciznosti mozemo dobiti:
import sys
print("x_max=",sys.float_info.max)
print("x_min=", sys.float_info.min)
print("eps=", sys.float_info.epsilon)
x_max= 1.7976931348623157e+308 x_min= 2.2250738585072014e-308 eps= 2.220446049250313e-16
S druge strane možemo korisiti i biblioteku Numpy za dobivanje osnovnih vrijednosti o fp-sustavu
import numpy as np
print(np.finfo(np.float64))
Machine parameters for float64 --------------------------------------------------------------- precision = 15 resolution = 1.0000000000000001e-15 machep = -52 eps = 2.2204460492503131e-16 negep = -53 epsneg = 1.1102230246251565e-16 minexp = -1022 tiny = 2.2250738585072014e-308 maxexp = 1024 max = 1.7976931348623157e+308 nexp = 11 min = -max ---------------------------------------------------------------
Sada ćemo vidjeti kako možemo dobiti npr. vrijednosti inf i nan
a=0.2e2000
print("a=",a)
b=float('inf')-float('inf')
print("b=", b)
a= inf b= nan
Dijeljnje s nulom, rezultira porukom upozorenja. U Matlabu bismo dobili Inf
c=1.0/0.0
print("c=", c)
--------------------------------------------------------------------------- ZeroDivisionError Traceback (most recent call last) Cell In[3], line 1 ----> 1 c=1.0/0.0 2 print("c=", c) ZeroDivisionError: float division by zero
Također sljedeća operacija signalizira na pretek. U Matlabu bismo računajući $2^{2000}$ dobili INF
d=2.0**2000
print("d=", d)
--------------------------------------------------------------------------- OverflowError Traceback (most recent call last) Cell In[4], line 1 ----> 1 d=2.0**2000 2 print("d=", d) OverflowError: (34, 'Result too large')
MATLAB je nastao kao sučelje za bazične biblioteke za linearnu algebru (BLAS). Ponašanje jednako MATLABu može se konfigurirati promjenom postavke errstate u biblioteci numpy.
import numpy as np
from collections import OrderedDict
olderr = np.seterr(all='ignore')
e=np.exp(1000)
print("e=", e)
f=np.log(0)
print("f=", f)
np.arange(3) / 0.
e= inf f= -inf
array([nan, inf, inf])
Strojni epsilon¶
print("eps=", sys.float_info.epsilon)
eps= 2.220446049250313e-16
def m_eps(func=float):
eps = func(1)
while func(1)+func(eps) != func(1):
eps1 = eps
eps = func(eps) / func(2)
return eps1
m_eps(float)
2.220446049250313e-16
x=1.0
y=2.0**(-55)
z=1.0
print("x=",x)
print("y=", y)
print("z=", z)
print("(x+y)-z=",(x+y)-z)
x= 1.0 y= 2.7755575615628914e-17 z= 1.0 (x+y)-z= 0.0
import numpy as np
a=1.0
c=1.0
b=-(1.e+8+1.e-8)
coeff= [a, b, c]
print("Roots=",np.roots(coeff))
Roots= [1.e+08 1.e-08]
x1=(-b+np.sqrt(b**2-4*a*c))/(2*a)
print("x1=",x1)
x2=(-b-np.sqrt(b**2-4*a*c))/(2*a)
print("x2=",x2)
x1= 100000000.0 x2= 1.4901161193847656e-08
x2=c/(a*x1)
print("x2=",x2)
x2= 1e-08
Računanje $\frac{\ln(1+x)}{x}$¶
Znamo $\frac{\ln(1+x)}{x}\approx 1$ za $x\approx 0$
np.log(1+3.e-16)/(3.0e-16)
0.7401486830834376
np.log(1+3e-16)/((1+3.e-16)-1)
0.9999999999999999
Sustav¶
import numpy as np
A = np.array([[17, 9], [1.7, 0.9]])
b = np.array([26,2.6])
x = np.linalg.solve(A,b)
print("x=",x)
x= [-0.58823529 4. ]
mu=1.7/17
A[1,1]=A[1,1]-mu*A[0,1]
b[1]=b[1]-mu*b[0]
print("A[1,1]=", A[1,1])
print("b[1]=", b[1])
A[1,1]= 1.1102230246251565e-16 b[1]= 4.440892098500626e-16
x[1]=b[1]/A[1,1]
x[0]=(26-9*x[1])/17
print("x[0]=", x[0])
print("x[1]=", x[1])
x[0]= -0.5882352941176471 x[1]= 4.0
Uočimo da smo u računalu dboli jedno rješenje a iz teoreije znamo da ih ima beskonačno mnogo.