Διάλεξη 3ης Οκτωβρίου 2016

Εντολές ανακύκλωσης. Η εντολή while

Αν $a$ είναι ένας θετικός πραγματικός αριθμός και $x$ είναι μια προσέγγιση της τετραγωνικής ρίζας του $a$ τότε $y = \frac{1}{2}\left(x + \frac{a}{x}\right)$ είναι μια καλύτερη προσέγγισή της. Αυτό το γεγόνός το οποίο σήμερα μπορούμε να δικαιολογήσουμε εύκολα, ήταν γνωστό στον Ήρωνα της Αλεξάνδρειας (10-70 μ.Χ.) και πιθανώς πολύ νωρίτερα. Για παράδειγμα, αν $a = 2$ και χρησιμοποιήσουμε $x = 1$ ως αρχική προσέγγιση του αριθμού $\sqrt{2}$ τότε έχουμε $y = 1.5$. Αν τώρα θέσουμε $x = 1.5$ υπολογίζουμε $y = \frac{17}{12} \approx 1.41666$, μια προσέγγιση με σφάλμα μόνο 0.0025. Αν χρησιμοποιήσoυμε τώρα $x = \frac{17}{12}$ έχουμε $y = \frac{577}{408} \approx 1.\mathbf{41421}5686$, μια προσέγγιση του $\sqrt{2}$ με πέντε σωστά δεκαδικά ψηφία!

Η μέθοδος για την προσέγγιση της τετραγωνικής ρίζας του $a$ που προκύπτει από τα παραπάνω είναι μια επαναληπτική διαδικασία η οποία τερματίζει όταν η προσέγγιση είναι, για τις ανάγκες μας, αρκετά καλή:

$x \leftarrow$ αρχική προσέγγιση του $\sqrt{a}$
όσο το $x$ δεν είναι αρκετά καλή προσέγγιση
$\qquad y\leftarrow \frac{1}{2}\left(x + \frac{a}{x}\right)$
$\qquad x\leftarrow y$
τέλος

Αυτή την επαναληπτική διαδικασία μπορούμε να την υλοποίησουμε στην Python με την εντολή αναλύκλωσης while, το συντακτικό της οποίας είναι:


while expression:
    statements

Οι εντολές statements εκτελούνται εφόσον η έκφραση expression είναι αληθής. Παρατηρήστε ότι ο τρόπος ομαδοποίησης των εντολών ανακλυκλωσης statements είναι πάλι η εσοχή (tab). Μπορούμε λοιπόν να υλοποιήσουμε τη μέθοδο του Ήρωνα για τον υπολογισμό της τετραγωνικής ρίζας με τις ακόλουθες εντολές:


a = 2
x = 1  # First approximation
while abs(x*x - a) > 1.0e-5:
    x = 0.5*(x + a/x)
print('The square root of', a, 'is approximately', x)

Μπορούμε να χρησιμοποιήσουμε την εντολή while για να εκτελέσουμε κάποιες εντολές ένα συγκεκριμένο αριθμό φορών, όπως για παράδειγμα, να διαβάσουμε δεδομένα:


i = 0   # counter
while i < 10:
    x = int(input('Enter an integer: '))
    if x <= 0:
        print('The number is non-positive')
    else:
        print('The number is positive')
    i = i + 1
print('Done!')

Οι παραπάνω εντολές θα ζητήσουν από το χρήστη να δώσει την τιμή της μεταβλητής x ακριβώς 10 φορές. Η μεταβλητή i χρησιμοποιείται ως μετρητής. Η αρχική τιμή του μετρητή είναι μηδέν και η τιμή αυτή αυξάνεται κατά ένα κάθε φορά ως η τελευταία εντολή μέσα στην ανακύκλωση. Μετά την έξοδο από την ανακύκλωση η μεταβλητή i έχει την τιμή 10.

Μπορούμε ακόμα να τερματήσουμε την ανακύκλωση πρόωρα χρησιμοποιώντας την εντολή break όπως στο παρακάτω παράδειγμα


s = 'Mississippi'
i = 0
while i < len(s):
    if s[i] == 'o':
        print('The letter o is in position', i)
        break 
    i = i + 1
if i == len(s):
    print('There is no o in the word', s)

Η εντολή break είναι χρήσιμη για να διαφύγουμε από τις λεγόμενες ατέρμονες ανακυκλώσεις, όπως αυτή στο παρακάτω παράδειγμα.


while 1:
    x = int(ínput('Pick a number between 1 and 100: '))
    if x >= 1 and x <= 100:
        break
print('You chose the number', x)

Μπορούμε να παραλείψουμε, προσωρινά, τις εντολές της ανακύκλωσης με την εντολή continue.


iter = 0
sum = 0
while iter < 10:
    x = int(input('Enter a positive integer: '))
    if x <= 0:
        continue
    sum = sum + x
    iter = iter + 1
print('The sum is', sum)

Ως ένα ακόμα παράδειγμα, ας θεωρήσουμε το πρόβλημα της εύρεσης της μικρότερης δύναμης του δύο πού είναι μεγαλύτερη ή ίση από ένα πραγματικό αριθμό $x$.


x = float(input('Enter a real number: '))
p = 1
while p < x:
    p = p * 2 
print('The smallest power of two greater than or equal to', x, 'is', p)

Ξεκινάμε με την μηδενική δύναμη του δύο την οποία και διπλασιάζουμε κάθε φορά που είναι μικρότερη από τον πραγματικό αριθμό $x$. Μόλις συμβεί αυτό, η ανακύκλωση τερματίζεται και τυπώνεται ένα κατάλληλο μήνυμα. Σημειώνουμε εδώ ότι θα μπορούσαμε να γράψουμε την εντολή ανακύκλωσης ως while p < x: p = p * 2, μια και πρόκειται για μια ανακύκλωση με μια μόνο (απλή) εντολή. Ο ενδιαφερόμενος αναγνώστης μπορεί να αναρωτηθεί για το προτέρημα ή όχι αυτού του γεγονότος αλλά και να βρεί πολλές χρήσιμες συμβουλές για την καλύτερη παρουσίαση του κώδικά του στον οδηγό καλού στύλ προγραμματισμού της Python.

Μια πολύ σημαντική σύμβαση, την οποία θα ακολουθούμε στο εξής, είναι ακόλουθη: η εντολή ανάθεσης x += y είναι ισοδύναμη με την εντολή x = x + y. Έτσι, μπορούμε να γράψουμε x += 1 για να αυξήσουμε την τιμή της μεταβλητής x κατά μια μονάδα. Ανάλογα ισχύουν και για τις εντολές ανάθεσης x -= y, x *= y, x /= y, x //= y και x **= y. Προσοχή, αν η τιμή της μεταβλητής x είναι δύο και η τιμή της μεταβλητής y είναι τρία τότε, μετά την εντολή x *= y + 1 η τιμή της μεταβλητής x θα είναι 8.