Python:
In [1]:
pi.n(digits=3)
Out[1]:
In [2]:
21==2*10+1
Out[2]:
Zapis liczby $21$ jest w systemie pozycyjnym ciagiem znaków (ang. string), "2" i "1".
In [3]:
x = 21
x
Out[3]:
In [4]:
str='21'
str
Out[4]:
wypiszmy te znaki jedem po drugim:
In [5]:
l = ['a','b','c']
i=0
for z in l:
print i,z
i = i+1
In [6]:
l = ['a','b','c']
for i in range(len(l)):
print i,l[i]
In [7]:
b,c = 1,2
print b,c
In [8]:
l = ['a','b','c']
for i,z in enumerate(l):
print i,z
In [9]:
list(enumerate(l))
Out[9]:
In [10]:
for b,c in [(0, 'a'), (1, 'b'), (2, 'c')]:
print b,c
In [11]:
str = '21'
for l in str:
print l
In [12]:
list(reversed(list(str)))
Out[12]:
In [13]:
for n,d in enumerate(reversed(list(str))):
print n,d
z tych znaków możemy "złożyć" liczbę, stosując wzór:
$$21 = 2\cdot 10^1 + 1\cdot 10^0. $$
In [14]:
int("a2")
In [15]:
int('12')
Out[15]:
In [16]:
l = []
for i in range(5):
l.append(2**i)
l
Out[16]:
In [17]:
[2**3 for i in range(5)]
Out[17]:
In [18]:
sum ( [int(d)*10^(n) for n,d in enumerate(reversed(list(str)))] )
Out[18]:
In [170]:
Out[170]:
Weźmy teraz liczbę $n$ będącą licznbą całkowitą w Sage:
In [19]:
n = 21
type(n)
Out[19]:
Chociaż tego nigdzie nie deklarowaliśmy, $n$ jest objektem Integer a nie typem prostym języka python "int". Magicznie zadziałał za nas preparser w Sage:
In [20]:
preparse('n=21')
Out[20]:
Objekt Integer ma wiele użytecznych metod, np.:
In [21]:
n.
In [22]:
n.nbits()
Out[22]:
In [23]:
str=n.binary()
str
Out[23]:
Jak możemy znając przedstawienie dziesiętne, obliczyć reprezentacje danej liczby w systemie binarnym?
Oczywiście mamy do tego narzędzia w Sage:
In [24]:
(21).binary()
Out[24]:
In [ ]:
Jednak jak można sobie poradzić ich nie mając (lub używając czystego pythona)?
Możemy do tego wykorzystać dzielenie z resztą i dzielenie modulo (lub innymi słowami znanego ze szkoły dzielenia z resztą). Wystartujmy od naszej liczby. Podzielmy ją z resztą przez 2, a następnie zapiszemy sobie resztę a wynik potraktujemy jako nową liczbę wejsciowa. Kontynuujać aż otrzymamy w wyniku zero, taka procedura da nam listę reszt. Liest ta będzie reprezentacją binarną liczby wyjsciowej, ale w odwróconej kolejności.
Na początej jednak wyróbujmy dzielenie z resztą:
In [25]:
print "modulo ",21%2
print "dzielenie ",21/2
print "dzielenie całkowite ", int(21)/int(2)
print "dzielenie z resztą z Sage ", (21).quo_rem(2)
Zauważmy, że operatory % i / dadzą nam poprawne wartości dzielenia modulo i części całkowitej z dzielenia tylko jeśli ich argumenty (tzn n i r) będą typami 'int'. W Sage kazda liczba jest automatycznie zamieniana na objekt np. Integer. Są trzy sposoby by obejść to niepotrzebne w tej chwili udogodnienie:
Poniżej znajduje się implementacja:
In [ ]:
In [29]:
%%python
n = 23
while n>0:
n,r = n//2,n%2
print n,r
In [28]:
n = 23
while n>0:
n,r = int(n)/int(2),n%2
print n,r
In [33]:
n=23
while n>0:
n,r = n.quo_rem(2)
print n,r
Zamiast na ekran, zapiszmy sobie wynik do tablicy, by można było z niego złożyć reprezentacje binarną liczby.
In [34]:
n=23
n_binary=[]
while n>0:
n,r = n.quo_rem(2)
n_binary.append(r)
Złożenie wymaga użycia operacji join, która w pythonie z listy robi ciąg znaków. (warto pamiętać, że odwrotną operacją jest "split").
In [40]:
str="".join([ i.str() for i in reversed(n_binary)])
str
Out[40]:
Na koniec sprawdźmy czy wynik jest poprawny, korzystając bezpośrednio z definicji reprezentacji binarnej:
In [41]:
sum ( [int(d)*2^(n) for n,d in enumerate(reversed(list(str)))] )
Out[41]:
Czyli jest OK!
W systemie dwójkowym można przedstawiać również liczby rzeczywiste. Na przykład ułamek dziesiętny o podstawie 2 można zapisać jako:
$$0.101_{2}=0\cdot 2^0 + 1 \cdot 2^{-1} + 0 \cdot 2^{-2} + 1 \cdot 2^{-3} = 0.625_{10}\;.$$
Liczby rzeczywiste w Sage są reprezentowane przez klasę reprezentującą liczby rzeczywiste. Jest ona w stanie obslugiwać liczby o dowolnej precyzji oraz posiada wiele użytecznych metod.
In [42]:
x=1.2
print type (x)
print preparse('x=1.2')
Można m.in. otrzymać reprezentację binarna danej liczby:
In [43]:
(0.625).str(base=2)
Out[43]:
W drugą stronę: tworząc liczbę rzeczywistą z ciągu znaków, możemy jawnie podać reprezentację:
In [44]:
x = RealNumber('0.101',base=2)
x
Out[44]:
Część całkowitą liczby rzeczywistej możemy uzyskać stosując zarówno funkcję pythonową floor jak i metodę floor:
In [45]:
x=1.2
print "funkcja floor",x,floor(x)
print "metoda floor",x,x.floor()
In [46]:
print "czesc dziesietna",x-floor(x)
In [138]:
Out[138]:
Aby wyznaczyć reprezentację dwójkową liczny rzeczywistej, możemy rozbić ją na część całkowitą i dziesiętną. Część całkowitą zamieniamy według znanego algorytmu ma postać dwójkową a z częścią dziesiętną postępujemy inaczej. Mnożymy ją przez 2 i zaposujemy części całkowite wyniku:
In [47]:
n=0.21
licznik=0
n_binary=[]
while True:
licznik=licznik+1
n=n*2
r=int(n)
n=n-floor(n)
n_binary.append(r)
if n==0 or licznik>20:
break
n_binary
Out[47]:
In [141]:
Out[141]:
In [140]:
Out[140]:
In [90]:
x=.1
In [91]:
Out[91]:
In [49]:
sign,mantissa,exponent=x.sign_mantissa_exponent()
sign,mantissa,exponent
Out[49]:
In [50]:
xx=N(5939122008594842*2^(-48))
In [51]:
xx
Out[51]:
In [52]:
xx.str(truncate=False)
Out[52]:
In [53]:
(mantissa*2^exponent).n()
Out[53]:
In [ ]:
In [ ]:
In [ ]:
In [54]:
x=0.4
In [55]:
x.str(base=2,truncate=False)
Out[55]:
In [ ]:
In [56]:
x.prec()
Out[56]:
In [57]:
sign,mantissa,exponent=x.sign_mantissa_exponent()
sign,mantissa,exponent
Out[57]:
In [58]:
(mantissa*2^exponent).n(digits=100)
Out[58]:
In [78]:
Out[78]:
Wyobraźmy sobie, że mamy 2-bitową mantysę i 2-bitowy eksponent. Wtedy:
$$1.b_1b_2\times 2^{k-2},$$ gdzie $b_1$ i $b_2$ mogą przybierać wartości $0$ i $1$ a $k$: $0,1,2,3$.
In [59]:
x=RR('1.01',base=2)
In [60]:
print x.str(base=2)
print x.str(base=10)
In [61]:
b=12
print "Liczba jest mniejsza niz :%d lub %d" % (b,b*2)
In [64]:
num_tbl=[[ r'$1.%d%d \times 2^{%d}$' %(b1,b2,k-2),(RR('1.%d%d'%(b1,b2),base=2)*2^(k-1)).exact_rational(),RR('1.%d%d'%(b1,b2),base=2)*2^(k-1)] for b1,b2,k in CartesianProduct([0,1],[0,1],[0,1,2,3])]
num_tbl.sort(key=lambda x:x[2])
# sortowanie tableli przez itemgetter
# from operator import itemgetter
# num_tbl.sort(key=itemgetter(2))
In [92]:
html.table( num_tbl )
Out[92]:
Cała arytmetyka jest reprezentowana przez zaledwie 16 różnych liczb:
In [66]:
len(num_tbl)
Out[66]:
In [67]:
nums=[ i[2] for i in num_tbl]
Narysujmy te liczby na osi liczbowej:
In [68]:
points(zip(nums,[0]*len(nums)),pointsize=25,ticks=[1/4,None]).show(xmin=0,xmax=4,figsize=[10,1] )
In [48]:
Out[48]:
Zbadajmy system 64 bitowych liczb zmiennoprzycinkowych mantysa ze znakiem 53bity + 11 bitów wykładnik:
In [69]:
x=1.0
In [70]:
x.nextabove().str(truncate=False)
Out[70]:
In [71]:
x.str(base=2)
Out[71]:
In [72]:
x.nextabove().str(base=2)
Out[72]:
In [73]:
x.nextbelow().str(base=2)
Out[73]:
In [74]:
x.nextbelow().str(truncate=False)
Out[74]:
In [75]:
x.nextabove().str(truncate=False)
Out[75]:
In [76]:
x.nextbelow().str(base=2)
Out[76]:
In [77]:
x.nextabove()-x
Out[77]:
In [78]:
x.nextbelow()-x
Out[78]:
In [79]:
print "%e" % 1234
In [80]:
x=21
In [81]:
x.str(base=2)
Out[81]:
In [149]:
Out[149]:
Liczba 0.1 nie jest reprezentowana dokładnie!
In [82]:
10 * (1.1 -1) - 1
Out[82]:
Należy unikać porównań typu:
if (x == 1.0)
{
....
}
In [83]:
type(1)
Out[83]:
In [84]:
1/2+1/3
Out[84]:
In [85]:
sum = 0.0
for i in range(1000000):
sum += 0.1
print(sum)
In [86]:
sum = 0.0
for i in range(1000000):
sum += 0.1
sum
Out[86]:
In [87]:
var('x')
Out[87]:
In [88]:
((x-1)^4).expand()
Out[88]:
In [89]:
plot(x^4 - 4*x^3 + 6*x^2 - 4*x + 1,(x,0.9996,1.0004) ) + plot((x-1)^4,(x,0.9996,1.0004),color='red',figsize=5 )
Out[89]:
@interact
def _(p=slider( range(2,10) ) ):
x=1.
xf=x.n(prec=p)
xf_lst=[]
while xf<=31:
xf_lst.append(xf)
xf=xf.nextabove()
x=1.
xf=x.n(prec=p)
while xf>=.1:
xf=xf.nextbelow()
xf_lst.append(xf)
# ,ticks=[1/4,None]
points(zip(xf_lst,[0]*len(xf_lst)),pointsize=25).show(xmin=0,xmax=31,figsize=[15,1] )
In [154]:
Out[154]:
In [96]:
Out[96]: