flowchart LR
P["το πρόγραμμά μας"] -->|"import math"| M["module math
pi · e · tau
sqrt · pow · isqrt · hypot
log · log2 · log10 · exp
sin · cos · tan · radians · degrees
floor · ceil · factorial · gcd"]
M -->|"math.sqrt(2)"| R["1.4142135..."]
Πληροφορική Ι
Εβδομάδα 2 · Πράξεις και Συμβολοσειρές
(Οδηγίες χρήσης του διαδραστικού κώδικα: δείτε την αρχική σελίδα.)
1 Αριθμητικοί τελεστές και προτεραιότητα
Η Python διαθέτει τους συνηθισμένους αριθμητικούς τελεστές, με μερικές λεπτομέρειες που αξίζει να προσέξουμε:
| Τελεστής | Πράξη |
|---|---|
+ |
Πρόσθεση |
- |
Αφαίρεση |
* |
Πολλαπλασιασμός |
/ |
Διαίρεση (πάντα επιστρέφει float) |
// |
Ακέραια διαίρεση (στρογγυλοποίηση προς το \(-\infty\)) |
% |
Υπόλοιπο διαίρεσης |
** |
Ύψωση σε δύναμη |
Η προτεραιότητα των πράξεων είναι:
- παρενθέσεις
- ύψωση σε δύναμη (
**, δεξιά προς αριστερά) - πολλαπλασιασμός / διαίρεση / υπόλοιπο (
*,/,//,%, αριστερά προς δεξιά) - πρόσθεση / αφαίρεση
Οι τελεστές επαυξημένης εκχώρησης (+=, -=, *=, /=, //=, %=, **=) συντομεύουν μια εκχώρηση όπου η ίδια μεταβλητή εμφανίζεται και στα δύο μέλη: το a += x είναι απλώς συντομογραφία του a = a + x.
1.1 Συνηθισμένα λάθη: διαίρεση με το μηδέν και υπερχείλιση (overflow)
Η διαίρεση (/, //, %) με παρονομαστή 0 δεν επιστρέφει κάποια ειδική τιμή — προκαλεί σφάλμα ZeroDivisionError, που σταματάει αμέσως την εκτέλεση:
Σε πολλές άλλες γλώσσες (C, Java, …) οι ακέραιοι έχουν σταθερό μέγεθος σε bits. Μια πράξη που ξεπερνάει το μέγιστο αποθηκεύσιμο μέγεθος προκαλεί υπερχείλιση (overflow) — συχνά αθόρυβα, δίνοντας λάθος (και μάλιστα ενίοτε αρνητικό!) αποτέλεσμα.
Οι ακέραιοι (int) της Python όμως έχουν απεριόριστο μέγεθος: μεγαλώνουν όσο χρειάζεται, χωρίς να «σπάνε» ποτέ.
Οι δεκαδικοί αριθμοί (float) όμως δεν έχουν απεριόριστο μέγεθος: αναπαρίστανται με σταθερό αριθμό bits (διπλής ακρίβειας IEEE-754), οπότε ένα αποτέλεσμα υπερβολικά μεγάλο για να αναπαρασταθεί προκαλεί κι εδώ υπερχείλιση — μερικές φορές με σφάλμα, μερικές φορές αθόρυβα με την ειδική τιμή inf (άπειρο):
2 Συμβολοσειρές
2.1 Συμβολοσειρές ως αλληλουχίες χαρακτήρων
Μια συμβολοσειρά (str) είναι μια αλληλουχία χαρακτήρων. Όπως και οι αριθμοί, μπορούμε να την αποθηκεύσουμε σε μεταβλητή και να προσπελάσουμε τμήματά της με δείκτες (index) και τεμαχισμό (slicing) — θα ξαναδούμε τους ίδιους μηχανισμούς σε λίστες σε λίγες εβδομάδες:
Σε αντίθεση όμως με τις λίστες, οι συμβολοσειρές είναι αμετάβλητες (immutable): δεν μπορούμε να αλλάξουμε έναν χαρακτήρα με εκχώρηση — το text[0] = 'x' προκαλεί σφάλμα TypeError. Κάθε “τροποποίηση” (π.χ. με τον τελεστή +) στην πραγματικότητα δημιουργεί μια εντελώς νέα συμβολοσειρά.
Ο τελεστής in ελέγχει αν μια συμβολοσειρά περιέχεται σε μια άλλη:
2.2 Μέθοδοι συμβολοσειρών
Η Python διαθέτει πλούσιο σύνολο μεθόδων για συμβολοσειρές:
| Σκοπός | Μέθοδοι |
|---|---|
| έλεγχος περιεχομένου | isalpha(), isdigit(), isalnum(), isspace(), islower(), isupper() |
| τροποποιημένο αντίγραφο | lower(), upper(), strip() (κόβει κενά από τις άκρες), replace(παλιό, νέο) |
| αναζήτηση | find(υπο-συμβολοσειρά), startswith(...), endswith(...) |
| διαχωρισμός σε λέξεις | split() |
Επειδή οι συμβολοσειρές είναι αμετάβλητες, όλες αυτές οι μέθοδοι επιστρέφουν νέα συμβολοσειρά — δεν αλλάζουν την αρχική.
2.3 Κωδικοποίηση χαρακτήρων: ord και chr
Η Python αναπαριστά κάθε χαρακτήρα ως έναν ακέραιο κωδικό (Unicode). Η συνάρτηση ord(χαρακτήρας) επιστρέφει τον κωδικό ενός χαρακτήρα, και η chr(κωδικός) κάνει το αντίστροφο:
Αυτή η αντιστοιχία χαρακτήρα-κωδικού είναι και η βάση της λεξικογραφικής σύγκρισης συμβολοσειρών, που θα δούμε στην Εβδομάδα 3: το 'a' < 'b' ισχύει επειδή ord('a') < ord('b').
2.4 Δομημένη εκτύπωση: f-strings
Πολύ συχνά θέλουμε να τυπώσουμε ένα μήνυμα που συνδυάζει σταθερό κείμενο με τιμές μεταβλητών, ελέγχοντας ταυτόχρονα πώς εμφανίζονται (πόσα δεκαδικά, σε τι πλάτος, με τι στοίχιση). Ο σύγχρονος τρόπος στην Python είναι οι f-strings: μια συμβολοσειρά με το πρόθεμα f, μέσα στην οποία ό,τι βρίσκεται σε άγκιστρα { } αποτιμάται και μπαίνει στη θέση του.
Μετά από : μέσα στα άγκιστρα δίνουμε μια προδιαγραφή μορφής: .2f για πλήθος δεκαδικών, έναν αριθμό για ελάχιστο πλάτος πεδίου, < ^ > για στοίχιση (αριστερά / κέντρο / δεξιά), 0 για συμπλήρωση με μηδενικά, , για διαχωριστικό χιλιάδων:
Μερικές ακόμα χρήσιμες μορφές — «πινακάκι» με στοιχισμένες στήλες, άλλες βάσεις αρίθμησης, και η μορφή {έκφραση=} που τυπώνει μαζί το όνομα και την τιμή (βολικό στον εντοπισμό σφαλμάτων):
Θα συναντήσετε και δύο παλαιότερους τρόπους: τη μορφοποίηση τύπου printf με τον τελεστή % ('%.2f' % score) και τη μέθοδο str.format() ('{:.2f}'.format(score)). Κάνουν την ίδια δουλειά, αλλά οι f-strings είναι πιο ευανάγνωστες και ο προτιμώμενος τρόπος από την Python 3.6 και μετά — θα τις χρησιμοποιούμε παντού από την Εβδομάδα 3 και έπειτα (και ήδη στις εφαρμογές αυτής της εβδομάδας, παρακάτω).
3 Βιβλιοθήκες και η βιβλιοθήκη math
Η Python “από μόνη της” ξέρει τους τελεστές +, *, ** κ.λπ., αλλά δεν ξέρει έτοιμες τη ρίζα, τον λογάριθμο ή το ημίτονο. Τέτοιες συναρτήσεις είναι οργανωμένες σε βιβλιοθήκες (libraries): αρχεία με έτοιμο κώδικα που φορτώνουμε μόνο όταν τους χρειαζόμαστε. Μια βιβλιοθήκη που έρχεται μαζί με την Python λέγεται και module — και το πιο βασικό για μαθηματικά είναι το math.
3.1 Η εντολή import
Για να χρησιμοποιήσουμε μια βιβλιοθήκη, την εισάγουμε με την εντολή import. Η συνηθισμένη μορφή φέρνει ολόκληρο το module κάτω από το όνομά του· έπειτα προσπελαύνουμε το περιεχόμενό του με την τελεία (module.όνομα):
Το math.sqrt διαβάζεται «η sqrt από το math». Το πρόθεμα math. ξεκαθαρίζει από πού προέρχεται το όνομα, ώστε δύο διαφορετικές βιβλιοθήκες να μπορούν να έχουν συνάρτηση με το ίδιο όνομα χωρίς σύγκρουση.
Υπάρχουν και δύο παραλλαγές της import:
from math import sqrt— γράφουμε σκέτοsqrt(2). Βολικό, αλλά αν αργότερα κάνουμεimportκαι άλλο module που έχει κι αυτόsqrt, το ένα «σκεπάζει» το άλλο.import math as m— χρήσιμο για βιβλιοθήκες με μεγάλο όνομα, όπως τοimport matplotlib.pyplot as pltπου είδαμε ήδη στην Εβδομάδα 1.
Αποφεύγουμε το from math import * (φέρνει όλα τα ονόματα μαζί): γεμίζει το πρόγραμμα με ονόματα άγνωστης προέλευσης.
3.2 Σταθερές και βασικές συναρτήσεις
Το math περιέχει τις σταθερές που χρειαζόμαστε συχνότερα, καθώς και συναρτήσεις για ρίζες, δυνάμεις και στρογγυλοποίηση προς ακέραιο:
3.3 Ρίζες, λογάριθμοι και εκθετική
Η math.log(x) είναι ο φυσικός λογάριθμος (βάση e). Με δεύτερο όρισμα δίνουμε άλλη βάση, ενώ οι log2 και log10 είναι έτοιμες συντομεύσεις. Η math.exp(x) υπολογίζει το e**x:
Οι τρεις αυτές συναρτήσεις έχουν πολύ διαφορετική «ταχύτητα ανάπτυξης» — ας τις δούμε στο ίδιο γράφημα (με το matplotlib της Εβδομάδας 1):
3.4 Τριγωνομετρικές συναρτήσεις
Ένα σημείο-παγίδα: οι math.sin, math.cos, math.tan δουλεύουν σε ακτίνια, όχι σε μοίρες. Οι math.radians και math.degrees κάνουν τη μετατροπή:
4 Όγκος σφαίρας και άλλων στερεών
Με απλές αριθμητικές πράξεις μπορούμε να υπολογίσουμε τον όγκο βασικών στερεών σωμάτων, δεδομένης της ακτίνας \(r\) (και, όπου χρειάζεται, του ύψους \(h\)):
\[ V_{\text{σφαίρα}} = \frac{4}{3}\pi r^3, \qquad V_{\text{κύλινδρος}} = \pi r^2 h, \qquad V_{\text{κώνος}} = \frac{1}{3}\pi r^2 h. \]
Παρατηρήστε ότι ο κώνος έχει πάντα το \(\frac{1}{3}\) του όγκου του κυλίνδρου με ίδια βάση και ύψος — ας το επαληθεύσουμε ρητά στον κώδικα, αντί απλά να το διαβάσουμε στην έξοδο:
Δοκιμάστε διαφορετικά r και h παραπάνω: η ισότητα cone_volume == cylinder_volume / 3 «τυχαίνει» να ισχύει ακριβώς εδώ, αλλά δεν είναι εγγυημένη.
Ο λόγος: δύο μαθηματικά ίσες ποσότητες μπορεί να υπολογιστούν με ελαφρώς διαφορετική σειρά πράξεων, και να καταλήξουν σε ελαφρώς διαφορετικό float λόγω στρογγυλοποίησης. Γι’ αυτό, όταν συγκρίνουμε αποτελέσματα πράξεων κινητής υποδιαστολής, προτιμάμε το math.isclose(...) αντί για το ==.
5 Μετατροπή Fahrenheit ⇄ Celsius
Οι κλίμακες Κελσίου (\(C\)) και Φαρενάιτ (\(F\)) συνδέονται με τον γραμμικό τύπο
\[ F = \frac{9}{5}C + 32 \quad \Longleftrightarrow \quad C = \frac{5}{9}(F - 32). \]
Δοκιμάστε το χαρακτηριστικό σημείο όπου οι δύο κλίμακες συμφωνούν: για \(C = -40\), βρείτε ότι και το fahrenheit βγαίνει \(-40\).
6 Το κρυπτοσύστημα του Καίσαρα
Το κρυπτοσύστημα του Καίσαρα είναι μια από τις αρχαιότερες γνωστές μεθόδους κρυπτογράφησης: κάθε γράμμα του μηνύματος αντικαθίσταται από το γράμμα που βρίσκεται \(k\) θέσεις μετά, στο κυκλικά επαναλαμβανόμενο αλφάβητο (μετά το Z ξαναγυρνάμε στο A). Αν αντιστοιχίσουμε στο A το 0, στο B το 1, …, στο Z το 25, τότε η κρυπτογράφηση ενός γράμματος με αριθμό θέσης \(p\) είναι μια πράξη αριθμητικής υπολοίπου (modular arithmetic):
\[ E(p) = (p + k) \bmod 26. \]
Για κλειδί \(k = 3\), το A γίνεται D, το B γίνεται E, … και κοντά στο τέλος του αλφαβήτου η ολίσθηση «τυλίγεται» πίσω στην αρχή χάρη στο mod 26:
flowchart LR
subgraph P ["απλό γράμμα (θέση p)"]
direction TB
pA["A · 0"]
pB["B · 1"]
pX["X · 23"]
pY["Y · 24"]
pZ["Z · 25"]
end
subgraph C ["κρυπτογράφημα ((p + 3) mod 26)"]
direction TB
cD["D · 3"]
cE["E · 4"]
cA["A · 0"]
cB["B · 1"]
cC["C · 2"]
end
pA --> cD
pB --> cE
pX --> cA
pY --> cB
pZ --> cC
Χρησιμοποιώντας τις ord και chr μπορούμε να υλοποιήσουμε την κρυπτογράφηση και την αποκρυπτογράφηση απευθείας πάνω σε αλφαβητικούς χαρακτήρες, αφήνοντας κενά και σημεία στίξης αμετάβλητα. Ο κώδικας εξετάζει τους χαρακτήρες του μηνύματος έναν-έναν με έναν βρόχο for (θα τον μελετήσουμε αναλυτικά στην Εβδομάδα 4), χτίζοντας σταδιακά το αποτέλεσμα στην τοπική μεταβλητή result:
Η αποκρυπτογράφηση είναι απλώς κρυπτογράφηση με αντίθετο κλειδί -k, χάρη στην αριθμητική υπολοίπου: το % στην Python δίνει πάντα μη αρνητικό αποτέλεσμα για θετικό διαιρέτη, οπότε η ολίσθηση «τυλίγεται» σωστά και προς τις δύο κατευθύνσεις.
Δοκιμάστε k = 13: είναι ο γνωστός ROT13, όπου η κρυπτογράφηση είναι η ίδια της η αντίστροφη — caesar_shift(caesar_shift(text, 13), 13) == text.
7 Σύνοψη
Σε αυτή την εβδομάδα είδαμε:
- Αριθμητικούς τελεστές, προτεραιότητα πράξεων, και τελεστές επαυξημένης εκχώρησης.
- Δύο συνηθισμένα σφάλματα:
ZeroDivisionError, και υπερχείλιση (overflow) — πώς αναπαρίστανται ακέραιοι καιfloatστη μνήμη, και γιατί μόνο ο δεύτερος υπερχειλίζει. - Συμβολοσειρές: δείκτες, τεμαχισμός, αμεταβλητότητα, τον τελεστή
in, μεθόδους (strip,split,replace, …), και τιςord/chr. - Βιβλιοθήκες και η εντολή
import(τρεις μορφές:import math,from math import ...,import math as m), και το πρόβλημα τουfrom ... import *. - Η βιβλιοθήκη
math: σταθερές (pi,e,tau), ρίζες και δυνάμεις (sqrt,isqrt,hypot), λογάριθμοι (log,log2,log10,exp), τριγωνομετρικές (sin/cos/tan— σε ακτίνια, μεradians/degreesγια μετατροπή), και βοηθητικές (floor,ceil,factorial,gcd,isclose). - Μαθηματικές εφαρμογές: όγκοι στερεών, μετατροπή θερμοκρασίας Fahrenheit ⇄ Celsius, και το κρυπτοσύστημα του Καίσαρα ως αριθμητική υπολοίπου (
%).
⤺ Πίσω στην αρχική σελίδα / πρόγραμμα μαθήματος · Διαφάνειες αυτής της εβδομάδας