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:

In [1]:
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

In [2]:
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

In [2]:
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

In [3]:
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

In [4]:
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.

In [5]:
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
Out[5]:
array([nan, inf, inf])

Strojni epsilon¶

In [7]:
print("eps=", sys.float_info.epsilon)
eps= 2.220446049250313e-16
In [8]:
def m_eps(func=float):
    eps = func(1)
    while func(1)+func(eps) != func(1):
        eps1 = eps
        eps = func(eps) / func(2)
    return eps1
In [9]:
m_eps(float)
Out[9]:
2.220446049250313e-16
In [10]:
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

Primjeri pogrešaka nastalih zbor prikaza brojeva u računalu¶

Rješavanje kvadratne jednadžbe¶

Ovo je jedan standardan primjer u kojem dolazi do dokidanja značajnih znamenaka, odnosno oduzimanja bliskih brojeva, te dobivamo pogrešno rješenje.

In [11]:
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]
In [12]:
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
In [13]:
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$

In [14]:
np.log(1+3.e-16)/(3.0e-16)
Out[14]:
0.7401486830834376
In [15]:
np.log(1+3e-16)/((1+3.e-16)-1)
Out[15]:
0.9999999999999999

Sustav¶

In [1]:
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.        ]
In [14]:
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
In [15]:
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.