Proste projekty i funkcje w języku Python
Wprowadzenie Przeczytaj Film samouczek Sprawdź się Dla nauczyciela
W obliczeniach matematycznych bardzo często konieczne jest wielokrotne powtarzanie tych samych, żmudnych obliczeń dla różnych danych wejściowych. W tej lekcji zajmiemy się przygotowaniem warsztatu narzędzi wspomagających takie obliczenia. Stworzymy funkcję, która będzie rozwiązywać równania kwadratowe wykorzystując algorytm stabilny.
Twoje cele
Dowiesz się, jak wykonywać obliczenia korzystając z funkcji w języku Python.
Porównasz rozwiązania równania kwadratowego obliczane algorytmem zwykłym (za pomocą wyznacznika delty) i stabilnym (bazującym na wzorach Viete'a).
Zweryfikujesz sposób prezentacji liczb w Pythonie.
Uzupełnisz wiedzę o module matplotlib.
Proste projekty i funkcje w języku Python
Źródło: licencja: CC 0.Przeczytaj
Przeanalizujmy funkcję kwadratową postaci:
f(x)=ax2+bx+c dla x∈x0,xn, a następnie rozwiążemy równanie kwadratowe:
ax2+bx+c=0
Przeanalizujmy schemat równania kwadratowego:
Przykład 1
Niech będzie dana funkcja:
f(x)=0.01x2−8x−0.01
Przygotujmy kod, który pozwoli na wizualizację wartości tej funkcji na ekranie komputera dla x∈-200, 1000. Wykorzystamy do tego bibliotekę matplotlib.
import matplotlib.pyplot as plt
def f(x):
return (0.01 * x * x) - (8 * x) - (0.01)
# tworzymy listy dla x oraz y = f(x) X = [x for x in range(-200, 1000)]
Y = [f(i) for i in X]
Z = [0 for i in X]
# tworzymy wykres - linia ciągła plt.plot(X, Y)
# linia pozioma dla y = 0 plt.plot(X, Z)
# tworzymy wykres - pojedyncze punkty, prawdopodobne miejsca zerowe plt.scatter([0, 800], [0, 0], c = "red")
# wyświetlamy linie pomocnicze plt.grid(True)
plt.show()
Łatwo zauważymy że funkcja posiada dwa miejsca zerowe. Możemy je oznaczyć w przybliżeniu, gdyż obliczając wartości tej funkcji dla argumentów 0 oraz 800 otrzymujemy wynik różny od zera, a więc to nie są idealne miejsca zerowe.
Znamy sposób rozwiązywania równania kwadratowego.
Musimy obliczyć wyróżnik równania kwadratowego, tzw. deltę.
Δ=b2−4ac Następnie na jej podstawie rozwiązujemy równanie.
DlaΔ>0istniejądwarozwiązania:x1=−b−Δ2aoraz:x2=−b+Δ2a DlaΔ=0istniejejednorozwiązaniex1=x2=−b2a
DlaΔ<0brakrozwiązań.
Przykład 2
Bazując na powyższym sposobie obliczmy wynik równania z dokładnością typową dla float, czyli 6 miejsc po przecinku. Dodatkowo obliczymy pierwiastek kwadratowy z delta, również z taką dokładnością.
def rownanie_kwadratowe_delta(a, b, c):
from math import sqrt
delta = round(b**2 - (4 * a * c), 6)
if delta > 0:
d = round(sqrt(delta), 6)
x1 = round((-b - d) / (2 * a), 6) x2 = round((-b + d) / (2 * a), 6) elif delta == 0:
x1 = round(-b / (2 * a), 6) x2 = x1
else:
# brak rozwiązań return None
return delta, x1, x2
# przykładowe wykonanie
rownanie_kwadratowe_delta(0.01, -8, -0.01) (64.0004, -0.00125, 800.00125)
Skuteczność i dokładność takiego sposobu obliczania można zakwestionować. Jeżeli wartość iloczynu 4ac jest mała w stosunku do wielkości b ** 2 to delta dąży do kwadratu z wartości b, a więc wyrażenie:
x1=−b±Δ2a
dąży do zera. Wówczas w programie komputerowym może powstać niedokładność wynikająca z zaokrąglenia liczb.
Przykład 3
Uruchomimy kod bazujący na takich wartościach a,b,c, dzięki którym zobaczymy taki przypadek
from math import sqrt a = 1
b = 40000 c = 1
delta = round(b ** 2 - (4 * a * c), 3) print(delta)
1599999996
pierwiastek = round(sqrt(delta), 3) print(pierwiastek)
40000.0
x1 = (-b + pierwiastek) / (2 * a) print(x1)
0.0
Aby zapobiec błędom zaokrągleń i niedokładności obliczeń, istnieje tzw. algorytm stabilny, który bazuje na wzorach Viete'a. W przypadku trójmianu kwadratowego o współczynnikach rzeczywistych, wzory te przyjmują postać:
x1+x2=−ba x1⋅x2=ca Wykorzystamy drugi z nich, tworząc następujące rozwiązanie:
Δ=b2−4ac
DlaΔ>0istniejądwamożliwerozwiązaniawzależnościodb:
b<0⇒x1=−b−Δ2aorazx2=ca⋅x1 b>0⇒x2=−b+Δ2aorazx1=ca⋅x2 DlaΔ=0istniejejednorozwiązaniex1=x2=−b2a
DlaΔ<0brakrozwiązań.
Przykład 4
Wykorzystajmy przedstawione wzory do napisania funkcji w języku Python i rozwiążemy równanie dla przykładowych wartości. W naszej funkcji wykorzystamy zaokrąglenie wartości obliczanych
zmiennych z dokładnością do 6 miejsc dziesiętnych.
def rownanie_kwadratowe_stabilne(a, b, c):
from math import sqrt
delta = round(b ** 2 - (4 * a * c), 6)
if delta > 0:
if b < 0:
x1 = round((-b - round(sqrt(delta), 6)) / (2 * a), 6) x2 = round(c / (a * x1), 6)
if b > 0:
x2 = round((-b + round(sqrt(delta), 6)) / (2 * a), 6) x1 = round(c / (a * x2), 6)
elif delta == 0:
x2 = round(-b / (2 * a), 6) x1 = x2
else:
# brak rozwiązań return None
return delta, x1, x2
# przykładowe wykonanie
rownanie_kwadratowe_stabilne(0.01, -8, -0.01) (64.0004, -0.00125, 800.00125)
Przykład 5
Przygotujmy kod, który pozwoli zobaczyć różnicę obliczeń dla algorytmu opartego o obliczanie delty oraz dla algorytmu stabilnego. Użyjemy konwencji f‑string, aby podać wynik z dokładnością do 25 miejsc po przecinku, wówczas zobaczymy różnicę w wynikach obliczeń. Dla algorytmu stabilnego różnica w wyniku pojawia się dopiero na 17 miejscu po przecinku!
def rownanie_kwadratowe_delta_test(a, b, c):
from math import sqrt
delta = round(b ** 2 - (4 * a * c), 6)
if delta > 0:
d = round(sqrt(delta), 6) x1 = (-b - d) / (2 * a) x2 = (-b + d) / (2 * a)
print(f"x1 = {x1:.25f}") print(f"x2 = {x2:.25f}")
x1 = round(x1, 6) x2 = round(x2, 6) elif delta == 0:
x1 = round(-b / (2 * a), 6) x2 = x1
else:
# brak rozwiązań return None
return delta, x1, x2
def rownanie_kwadratowe_stabilne_test(a, b, c):
from math import sqrt
delta = round(b ** 2 - (4 * a * c), 6)
if delta > 0:
d = round(sqrt(delta), 6)
if b > 0:
x1 = (-b - d) / (2 * a) x2 = c / (a * x1)
print(f"x1 = {x1:.25f}") print(f"x2 = {x2:.25f}")
x1 = round(x1, 6) x2 = round(x2, 6)
if b < 0:
x2 = round((-b + d) / (2 * a), 6) x1 = round(c / (a * x2), 6)
elif delta == 0:
x2 = round(-b / (2 * a), 6) x1 = x2
else:
# brak rozwiązań return None
return delta, x1, x2
# przykładowe wykonanie
rownanie_kwadratowe_delta_test(0.001, 7845369758436, 0.0001) x1 = -7845369758436000.0000000000000000000000000
x2 = 0.0000000000000000000000000
(6.154982664658214e+25, -7845369758436000.0, 0.0)
rownanie_kwadratowe_stabilne_test(0.001, 7845369758436, 0.0001) x1 = -7845369758436000.0000000000000000000000000
x2 = -0.0000000000000000127463718
(6.154982664658214e+25, -7845369758436000.0, -0.0) Dla zainteresowanych
Możemy w prosty sposób pokazać błędy wynikające z niedokładności języka programowania.
W przypadku języka Python wystarczy prosta pętla odliczająca wartości od 0 do 1, z krokiem co 0.1:
x = 0.0
print(f"Pętla while się rozpocznie, x ma teraz wartość {x:f}.")
while x <= 1:
print(x)
if x == 0.3:
print('Jest 0.3') if round(x, 1) == 0.3:
print('Jest w zaokrągleniu 0.3') if x == 0.4:
print('Jest 0.4')
if x == 1:
print('Koniec')
x += 0.1
print(f"Pętla while zakończona, x ma teraz wartość {x:f}.") print(f"x ma wartość bez formatowania float {x}.")
# wynik działania:
Pętla while się rozpocznie, x ma teraz wartość 0.000000.
0.0 0.1 0.2
0.30000000000000004 Jest w zaokrągleniu 0.3 0.4
Jest 0.4 0.5 0.6 0.7
0.7999999999999999 0.8999999999999999 0.9999999999999999
Pętla while zakończona, x ma teraz wartość 1.100000.
x ma wartość bez formatowania float 1.0999999999999999.
Już wiesz
Niektóre algorytmy zachowują się niestabilnie przy pewnych zestawach danych wejściowych.
Komputery nie są w stanie dokładnie przechowywać pewnych liczb w swojej pamięci, ponieważ w komputerze liczby wymierne przechowywane są w postaci binarnej, zgodnie z formatem IEEE 754.
Słownik
matplotlib
biblioteka służąca do przedstawienia obrazów złożonych z punktów o współrzędnych x oraz y (wykresów, histogramów, rozkładów itp.); moduł matplotlib nie jest dostępny w standardowej instalacji Pythona; należy zainstalować go korzystając z mechanizmu pip
zaokrąglanie liczb
gdy zaokrąglamy liczbę dziesiętną do pewnego ustalonego rzędu, a więc do określonej liczby po przecinku, sprawdzamy cyfrę rzędu niższego; jeśli jest mniejsza od 5, wówczas pozostawiamy zaokrąglaną wartość niezmienną, w przeciwnym wypadku zwiększamy ją o 1; przykład zaokrąglenia liczby 0.020006 do 2 miejsc po przecinku to 0.02, a do 5 miejsc po przecinku to 0.02001
wzory Viete'a
wzory wiążące współczynniki wielomianów i ich pierwiastki, ich autorem był Francois Viete, Francuz, który w XVI w. jako pierwszy wprowadził oznaczenia literowe dla zmiennych; w trakcie wojny
francusko‑hiszpańskiej złamał szyfr używany przez Hiszpanów f‑string
w Pythonie obecne od wersji 3.6, jest to sposób zapisu zmiennych w łańcuchu znaków przeznaczonym
do wypisania funkcją print() - dokładnie opisany w dokumencie PEP 498 -- Literal String Interpolation; zakłada format: f"Napis, a w nim {zmienna} do wypisania"
IEEE 754
standard zapisu zmiennoprzecinkowego, opracowany przez Williama Kahenema, definiuje 32‑bitowe oraz 64‑bitowe liczby zmiennoprzecinkowe
Film samouczek
Polecenie 1
Przeanalizujmy rozwiązanie równania kwadratowego.
Polecenie 2
Wykonaj program przedstawiony na filmie.
Film dostępny na portalu epodreczniki.pl
Źródło: Contentplus.pl Sp. z o.o., licencja: CC BY-SA 3.0.
Nagranie filmowe dotyczące stabilnego algorytmu rozwiązywania równania kwadratowego.
Sprawdź się
Ćwiczenie 1
W dowolnym środowisku wykonaj poniższy kod i porównaj wynik z poniższymi wykresami. Następnie odpowiedz na pytanie.
X = [x for x in range(-50, 50)]
A = [x * x * 1.14 for x in range(-50, 50)]
B = [i * j for i, j in enumerate(A)]
import matplotlib.pyplot as plt plt.plot(X, A)
plt.plot(X, B) plt.grid(True) plt.show()
Wykres 1:
Wykres 2:
輸
Wykres 3:
Prawidłowy wykres to:
Wykres 2 Wykres 1 Wykres 3
Brak wykresu - ten kod wygeneruje błąd: TypeError: 'int' object is not iterable
Podaj argumenty przemawiające za twoją odpowiedzią. Zapisz swoje spostrzeżenia.
Uzupełnij
Ćwiczenie 2
Zdefiniuj funkcję testowa(fun_nazwa, a, b), która zbuduje listę elementów o zakresie (a, b), które mają być parametrami polecenia range(a, b). Wartość tych elementów ma być obliczana na podstawie
醙
funkcji fun_nazwa(x), która musi być osobno zdefiniowana analogicznie jak na przykładzie.
Funkcja testowa() powinna zwrócić listę trzech wartości:
sumę tych elementów
średnią arytmetyczną
wartość maksymalną
Dane wejściowe: fun_nazwa - nazwa zewnętrznej funkcji str, a, b - liczby int
Dane wyjściowe: [suma, średnia, maximum] - list
# tu przykładowy kod dla ucznia - jak można przekazać funkcję jako parametr
def f1(x):
return x * (x / 2.34)
def f2(x):
return -x * (x / 3.4)
def testowa(fun, a, b):
return fun(a), fun(b)
# przykład wywołania funkcji przekazanej jako parametr print(testowa(f1, 3, 5))
# (3.8461538461538467, 10.683760683760683)
print(testowa(f2, 3, 5))
# (-2.6470588235294117, -7.352941176470589)
# przykładowe wykonanie funkcji testowej def fq(x):
return x ** 4 + (1.84 * x ** 3) - (5.41 * x ** 2)
def testowa(fun, a, b):
# definicja funkcji obliczającej...
return [sm, sr, mx]
wynik = testowa(fq, -100, 300) print(wynik)
[487613332826.0, 1219033332.065, 8041239995.75]
Opisz twoje uzasadnienie do kodu napisanej funkcji.
Uzupełnij
Ćwiczenie 3
Zdefiniuj funkcję testowa(a, b, c), która obliczy algorytmem stabilnym oraz niestabilnym rozwiązanie równania kwadratowego i zwróci różnicę wyników.
Funkcja powinna działać tylko dla delta > 0, w innym przypadku powinna zwrócić wartość None. Funkcja powinna zwrócić tuplę, zawierającą wartości bezwzględne różnic między x1 oraz x2 dla obu sposobów obliczania.
Zwracane dane powinny mieć format: (|x1_2 - x1_1|, |x2_2 - x2_1|)
Opisz twoje uzasadnienie do kodu napisanej funkcji.
Uzupełnij
醙
Dla nauczyciela
Autor: Karolina Biegus Przedmiot: Informatyka
Temat: Proste projekty i funkcje w języku Python Grupa docelowa:
III etap edukacyjny, liceum ogólnokształcące, technikum Podstawa programowa:
Zakres podstawowy i rozszerzony Cele kształcenia – wymagania ogólne
2) Programowanie i rozwiązywanie problemów z wykorzystaniem komputera oraz innych urządzeń cyfrowych:
układanie i programowanie algorytmów, organizowanie, wyszukiwanie i udostępnianie informacji, posługiwanie się aplikacjami komputerowymi.
Zakres rozszerzony
II. Programowanie i rozwiązywanie problemów z wykorzystaniem komputera i innych urządzeń cyfrowych.
Uczeń spełnia wymagania określone dla zakresu podstawowego, a ponadto:
2. stosuje zasady programowania strukturalnego i obiektowego w rozwiązywaniu problemów;
Kształtowane kompetencje kluczowe:
kompetencje obywatelskie;
kompetencje cyfrowe;
kompetencje osobiste, społeczne i w zakresie umiejętności uczenia się;
kompetencje matematyczne oraz kompetencje w zakresie nauk przyrodniczych, technologii i inżynierii.
Cele operacyjne (językiem ucznia):
Dowiesz się, jak wykonywać obliczenia korzystając z funkcji w języku Python.
Porównasz rozwiązania równania kwadratowego obliczane algorytmem zwykłym (za pomocą wyznacznika delty) i stabilnym (bazującym na wzorach Viete'a).
Zweryfikujesz sposób prezentacji liczb w Pythonie.
Uzupełnisz wiedzę o module matplotlib.
Strategie nauczania:
konstruktywizm;
konektywizm.
Metody i techniki nauczania:
dyskusja;
rozmowa nauczająca z wykorzystaniem multimedium i ćwiczeń interaktywnych.
Formy pracy:
praca indywidualna;
praca w parach;
praca w grupach;
praca całego zespołu klasowego.
Środki dydaktyczne:
komputery z głośnikami, słuchawkami i dostępem do internetu;
zasoby multimedialne zawarte w e‑materiale;
tablica interaktywna/tablica, pisak/kreda;
oprogramowanie dla języka Python 3 (lub nowszej wersji), w tym PyCharm lub IDLE.
Przebieg lekcji Przed lekcją:
1. Przygotowanie do zajęć. Nauczyciel loguje się na platformie i udostępnia e‑materiał: „Proste projekty i funkcje w języku Python”. Nauczyciel prosi uczniów o zapoznanie się z treściami w sekcji
„Przeczytaj”.
Faza wstępna:
1. Nauczyciel wyświetla temat i cele zajęć. Prosi uczniów, by na podstawie wiadomości zdobytych przed lekcją zaproponowali kryteria sukcesu.
2. Rozpoznanie wiedzy uczniów. Nauczyciel zadaje uczniom pytania dotyczące ich aktualnego stanu wiedzy w obszarze poruszanego tematu i programowania, np.
– na czym polega zaokrąglanie liczb?
– do rozwiązywania jakich równań możemy zastosować wzory Viete'a?
– czym się charakteryzują algorytmy stabilne?
Chętni uczniowie udzielają na nie odpowiedzi.
Faza realizacyjna:
1. Uczniowie analizują przykład z sekcji „Przeczytaj” i powtarzają zaprezentowane rozwiązanie na swoim komputerze.
2. Praca z multimedium. Nauczyciel wyświetla zawartość sekcji „Film samouczek”, czyta treść polecenia nr 1 „Przeanalizujmy rozwiązanie równania kwadratowego.” i omawia kolejne kroki rozwiązania.
3. Ćwiczenie umiejętności. Uczniowie wykonują indywidualnie ćwiczenie nr 1, a następnie porównują swoje odpowiedzi z kolegą lub koleżanką.
4. Uczniowie w parach wykonują ćwiczenia nr 2 i 3. Nauczyciel sprawdza poprawność wykonanych zadań, omawiając je wraz z uczniami.
Faza podsumowująca:
1. Nauczyciel ponownie wyświetla na tablicy temat i cele lekcji zwarte w sekcji „Wprowadzenie”.
W kontekście ich realizacji następuje omówienie ewentualnych problemów z rozwiązaniem ćwiczeń z sekcji „Sprawdź się”.
2. Nauczyciel prosi uczniów o podsumowanie zgromadzonej wiedzy w zakresie programowania w języku Python.
Praca domowa:
1. Uczniowie wykonują polecenie nr 2 z sekcji „Film samouczek”.
Materiały pomocnicze:
Oficjalna dokumentacja techniczna dla języka Python 3 (lub nowszej wersji).
Oficjalna dokumentacja techniczna dla oprogramowania PyCharm lub IDLE.
Wskazówki metodyczne:
Treści w sekcji „Film samouczek” można wykorzystać na lekcji jako podsumowanie i utrwalenie wiedzy uczniów.