Dzisiaj będzie o długich liczbach. Wiedzieliście, że Python w stałej Pi zawiera tylko 48 cyfr po przecinku? (a przynajmniej wersja 2.6) 3.141592653589793 (odtąd błędnie) 115997963468544185161590576171875. To stanowczo za mało! Tyle to ja liczyłem na liczydle w przedszkolu A ja chciałbym wiedzieć jaka jest liczba pięciotysięczna po przecinku
Zademonstruję 3 metody liczenia liczby Pi.
Od razu mówię, nie pytajcie mnie o nic w związku z tymi metodami, bo zazwyczaj rozumiem tylko wstęp i pierwszy wzór z opisu.
I. Metoda Wallisa
Posłużymy się takim fajnym tworem jak generator (yield w pętli zamiast return)
def wallisFormulaGenerator(counterMax):
counter = 0
while(counter <= counterMax):
counter += 1
yield (4*(counter**2))/(4*(counter**2)-1)
def gimmePiBaby(loops):
result = 1
for value in wallisFormulaGenerator(loops):
result *= value
return 2*result
print(gimmePiBaby(10000))
Ta metoda jest najsłabsza, po 18 obrotach mamy dopiero 3.1, po 492 3.14, a dopiero po 8476 3.1415.
II. Metoda Leibnitza
W moim przypadku mocno oszukana ta metoda, ale działa poprawnie. I dużo szybciej!
minus = True
partial = 1
denominator = 3
for i in range(100000):
if minus:
partial -= 1/denominator
minus = False
else:
partial += 1/denominator
minus = True
denominator += 2
result = 4 * partial
Jest lepiej, obliczenia wykonywały się 3x szybciej niż poprzednio.
III. Metoda Abrahama Sharpa
Najwydajniejsza z wyżej przedstawionych. Na pewno są wydajniejsze, ale dla określenia liczby nr 5000 wystarczy. Aby wypisać tyle liczb ile nas interesuje, zwykły obiekt typu float nie wystarczy, potrzebujemy biblioteki BigFloat. Niestety nie daje się zainstalować z wersją 3 Pythona mimo użycia 2to3, więc pozostaje wbudowane w Ubuntu 2.6.
import bigfloat
with bigfloat.precision(17000):
minus = True
partial = bigfloat.BigFloat(1)
denominator = 3
for i in range(1, 500000):
if minus:
partial -= (1/((bigfloat.pow(3,i))*denominator))
minus = False
else:
partial += (1/((bigfloat.pow(3,i))*denominator))
minus = True
denominator += 2
result = 6 * ((1/bigfloat.sqrt(3)) * partial)
Mój procek za 45zł 500 000 obrotów wykonał w 2339 sek., a dzisiejszy wpis sponsoruje cyferka 1 będąca wartością pięciotysięczną po przecinku.
Mam nadzieję, że chociaż gimnazjalistom algorytmy się przydadzą…
Zastanawiało Was kiedyś o ile dokładnie wzrośnie całkowita zawartość alkoholu gdy do piwa dodamy „u-boota” (50tkę wódki)? A o ile spadnie gdy to piwo zbeszcześcimy dodaniem soku malinowego? Chodzi mi o dokładne wartości, a nie jakieś tam „no pewnie z 2% jak nic”. Dzisiaj się dowiecie
Całość napisałem w Pythonie żeby się trochę wdrożyć. Dla Windowsa jest bardzo fajna rzecz: Portable Python. Instalujesz na pendraka i niezależnie od maszyny odpalasz interpreter. Do całości dołączony jest całkiem zgrabny edytor PyScripter.
Dobra, do rzeczy. Potrzebna będzie wiedza przedgimnazjalna — mnożenie, dzielenie i trochę procentów. Wynikowy program obsługuje się tak:
#!/usr/bin/env python
from shaker import Shaker, ShakerDisplayer
shaker = Shaker()
shaker.addIngredient('piwo', 500, 5.7)
shaker.addIngredient('wodka', 50, 40)
shaker.addIngredient('sok malinowy', 25, 0)
ShakerDisplayer.displayShakerDetails(shaker, 89, True)
Otrzymamy poniższy tekst:
Skladniki drinka:
25.00ml sok malinowy
30.00ml wodka
48.50ml alcohol
471.50ml piwo
Calkowita zawartosc alkoholu w drinku: 8.43%
Calkowita zawartosc alkoholu w drinku (wyrazona w gramach): 38.32g
Prawdopodobna liczba promili dla faceta o wadze 89kg wynosi 0.62‰
W pliku (module!) shaker.py stworzymy sobie 2 klasy: Shaker i ShakerDisplayer. Jak linijki nie mieszczą się w okienku to można przesuwać strzałkami na klawiaturze
#!/usr/bin/env python
import unicodedata
from numbers import Number
class Shaker:
def __init__(self, shakerCapacity = 1000000):
# Zakladamy, ze pojemnosc shakera jest nieograniczona ;-)
self._shakerCapacity = shakerCapacity
# Inicjalizuje dictionary dla przechowywania klucz => wartosc
# Klucz dla alkoholu jest w skladnikach zawsze
self._drinkIngredients = {'alcohol' : 0}
def addIngredient(self, name, amount, alcoholPercentage = 0):
# Gdyby komus zachcialo sie wprowadzac inne wartosci niz numerki i wartosci dodatnie
if not isinstance(amount, Number) or not isinstance(alcoholPercentage, Number) or alcoholPercentage < 0 or amount < 0:
# Formatowanie za pomoca {} zadziala od Pythona 3.1+
raise ValueError('Podano {} i {} dla {}'.format(amount, alcoholPercentage, name))
# Sprawdzam czy jest wystarczajaco duzo miejsca w shakerze
spaceInShakerLeft = self._shakerCapacity - self.totalLiquidAmount()
if spaceInShakerLeft >= amount:
self._storeNewIngredient(name, amount, alcoholPercentage)
else:
# Jak za malo to dolewam tylko tyle ile sie zmiesci
self._storeNewIngredient(name, spaceInShakerLeft, alcoholPercentage)
def _storeNewIngredient(self, name, amount, alcoholPercentage):
# Licze objetosc czystego alkoholu w plynie
liquidAlcohol = 0
if alcoholPercentage > 0:
liquidAlcohol = (amount * alcoholPercentage) / 100
self._drinkIngredients['alcohol'] += liquidAlcohol
# Sprawdzam czy w drinku jest juz dany skladnik
if self._drinkIngredients.get(name) == None:
self._drinkIngredients[name] = amount - liquidAlcohol
else:
self._drinkIngredients[name] += amount - liquidAlcohol
def getAllDrinkIngredients(self):
# Wypluwam czysty dictionary ze skladnikami
return self._drinkIngredients
def totalLiquidAmount(self):
# Zliczam objetosc wszystkich skladnikow w shakerze
total = 0
for value in self._drinkIngredients.values():
total += value
return total
def getTotalLiquidAlcohol(self):
return self._drinkIngredients['alcohol']
def getTotalAlcoholPercentage(self):
# Licze calkowity procent alkoholu w drinku
return (self.getTotalLiquidAlcohol() / self.totalLiquidAmount()) * 100
def getTotalAlcoholInGrams(self):
# Przeliczam ml alkoholu na gramy
return 0.79 * self.getTotalLiquidAlcohol()
def computeAlcoholPromillesPerWeight(self, weight, man = True):
# PRZYBLIZONA zawartosc procentowa plynow ustrojowych w zaleznosci od plci
humanFluidsPercentage = 0.7 if man == True else 0.6
return self.getTotalAlcoholInGrams() / (humanFluidsPercentage * weight)
def pourOutDrink(self, amount):
"""
Metoda wlasciwie niepotrzebna. Mozna wylac (wypic!) czesc zawartosci
shakera i sobie potem dolewac kolejne skladniki.
"""
if amount >= self.totalLiquidAmount():
self._drinkIngredients = {'alcohol' : 0}
else:
percentage = amount / self.totalLiquidAmount()
for key, value in self._drinkIngredients.items():
self._drinkIngredients[key] -= self._drinkIngredients[key] * percentage
Klasa powyżej policzy to co trzeba. Wyliczenia dotyczące promili w organizmie należy traktować jako mocno przybliżone. Całej dawki alkoholu nie przyjmujemy w końcu w 1 sekundzie, organizm na bieżąco spala truciznę. Poza tym zależy czy i co się jadło itp. itd., nie wiem, nie znam się.
Teraz jeszcze klasa, która zajmie się wyświetlaniem (a raczej metoda statyczna).
class ShakerDisplayer:
def displayShakerDetails(shaker, weight, man = True):
if not isinstance(shaker, Shaker):
raise ValueError('Podano argument klasy {}'.format(shaker.__class__))
print('Skladniki drinka:')
for key,value in shaker.getAllDrinkIngredients().items():
# Zaokraglamy i wymuszamy 2 miejsca po przecinku
print('{:.2f}ml {}'.format(value,key))
print('Calkowita zawartosc alkoholu w drinku: {:.2f}%'.format(shaker.getTotalAlcoholPercentage()))
print('Calkowita zawartosc alkoholu w drinku (wyrazona w gramach): {:.2f}g'.format(shaker.getTotalAlcoholInGrams()))
# Nie znam lepszej metody na wyswietlenie znaku promila niz unicodedata.lookup('PER MILLE SIGN')
# Ma ktos lepszy pomysl?
print('Prawdopodobna liczba promili dla {} o wadze {}kg wynosi {:.2f}{}'.format('faceta' if man == True else 'kobiety', weight, shaker.computeAlcoholPromillesPerWeight(weight,man), unicodedata.lookup('PER MILLE SIGN')))
Gdyby potraktować nasz żołądek jak taki shaker, to po wpisaniu pół litra wódki + 2 piwa + litrowy sprite da nam:
Skladniki drinka:
300.00ml wodka
257.00ml alcohol
1000.00ml sprite
943.00ml piwo
Calkowita zawartosc alkoholu w drinku: 10.28%
Calkowita zawartosc alkoholu w drinku (wyrazona w gramach): 203.03g
Prawdopodobna liczba promili dla faceta o wadze 89kg wynosi 3.26‰
No nic, na zdrowie i pozdro dla wszystkich Pythonowców! Leniuchom podaję link do gotowych plików.
Mamy niedzielę. W ramach leniuchowania zachciało mi się poznać jakiś nowy język programowania. Padło na Pythona (nieznacznie wygrał z Rubym).
Na pierwszy rzut oka to w zasadzie taki JavaScript ogólnego przeznaczenia bez przeglądarki. Python reklamowany jest jako język typu batteries included, czyli standardowa biblioteka powinna zawierać wszystko to, co w typowych zastosowaniach programista potrzebuje.
Od razu widać puryzm kodu Pythona. Żadnych klamerek, żadnych średników — wszystko załatwiamy wcięciami i końcami linii. „Kompresja kodu” widoczna jest na każdym kroku, np. funkcje deklarujemy poprzez def, a nie przydługawe function, obiekty tworzymy bez new. Weźmy na przykład najprostszą funkcję żądającą od użytkownika wpisania z klawiatury jakiejś liczby:
def getIntInput(message):
while True:
try:
return int(input(message))
except ValueError:
print("You were supposed to enter integer!")
W 6 liniach mamy załatwioną prośbę o wpisanie czegoś, przetworzenie wejścia i wyłapanie ewentualnych błędów. Funkcja nie odczepi się od użytkownika dopóki nie wpisze poprawnie jakichś cyferek.
wiek = getIntInput("Podaj rok urodzenia")
Poniżej w punktach ciekawostki, które w Pythonie są, a których nie ma w PHP (tyle co w ciągu kilku godzin udało mi się wyłapać):
- wspomniane już braki klamerek i średników — czy naprawdę potrzebujemy tego wszystkiego w PHP?
- wszystkie metody publiczne — tego nie popieram, może powodować bajzel w API; zgodnie z konwencją metody prywatne należy oznaczać przedrostkiem _
- fajne konstrukcje przy iterowaniu: for zmienna in array oraz for zmienna in range(5)
- dziwne zasady dokumentowania kodu — komentarze idą po deklaracji klasy czy metody
- array comprehension (nawet nie wiem jak to przetłumaczyć) — w jednej linijce możemy stworzyć nową tablicę na podstawie starej i przejechać jakąś funkcją po każdej wartości przed dodaniem:
nowaTablica = [funkcja(wartosc) for wartosc in staraTablica]
- proste losowanie:
zagadka = random.choice(["wartosc1","wartosc2","wartosc3"])
- tuple, czyli niedająca się modyfikować tablica; co ciekawe, funkcje bardzo często zwracają to ustrojstwo, możemy od razu złapać je do dwóch różnych zmiennych
wynik1, wynik2 = funkcja()
- obiekt None zamiast null
- == i != do sprawdzania wartości zmiennych, is i is not do porównywania z None lub referencji, mało tego, możliwa jest konstrukcja 0 <= a <= 10
- próba porówania if „3” < 4 wywali TypeError
- konstrukcja final do kompletu z try/except
- bajer dla mnie: if szukanaZmienna in tablica oraz if „wyraz” in przeszukiwanyString
- nie ma czegoś tak paskudnego jak RESOURCE
Tyle na początek. Widzę, że Python to fajna sprawa. O wszystkim pomyśleli. Nawet o wbudowaniu bazy danych sqlite w bibliotekę standardową. Jeżeli ktoś waha się czego by tu nowego się pouczyć to polecam!
P.S.: Tak, wiem, na tych waszych polibudach Pythona uczą już na I roku, ble ble srutututu. Samoucy typu np. ja muszą sami. Dobra, kończę, bo i piwo mi się skończyło