Pascal, απλοί τύποι, τελεστές και εκφράσεις 15 Νοεμβρίου 2011 1 Γενικά Στην standard Pascal ορίζονται τέσσερις βασικοί τύποι μεταβλητών: integer: Παριστάνει ακέραιους αριθμούς από το -32768 μέχρι και το 32767, real: παριστάνει αριθμούς κινητής υποδιαστολής από το 3.4 10 38 μέχρι το 3.4 10 38 τόσο θετικούς όσο και αρνητικούς, boolean: παριστάνει τις δύο τιμές της άλγεβρας Boole δηλαδή true και false, και char: παριστάνει χαρακτήρες π.χ. 'a', 'b', 'F' κτλ. Επίσης υπάρχουν και οι παρακάτω αριθμητικοί τελεστές: + Πρόσθεση, - αφαίρεση, / διαίρεση, * πολλαπλασιασμός, div ακέραια διαίρεση, mod ακέραιο υπόλοιπο. οι οποίοι όταν εφαρμόζονται κατάλληλα παράγουν αριθμητικές εκφράσεις. Οι αριθμητικές εκφράσεις μπορούν να συγκριθούν με τους συσχετιστικούς τελεστές: < μικρότερο, > μεγαλύτερο, <= μικρότερο ή ίσο, >= μεγαλύτερο ή ίσο, 1
= ίσο, <> διάφορο. Το απότελεσμα που προκύπτει είναι μια λογική τιμή true ή false, δηλαδή οι συσχετιστικοί τελεστές παράγουν τις λογικές τιμές ναι ή όχι. Οι λογικές τιμές true και false ή εκφράσεις που μπορούν να αποτιμηθούν ως true ή false μπορούν να συνδυαστούν με λογικούς τελεστές για να παράξουν πιο σύνθετες λογικές εκφράσεις. Αυτοί είναι: and Λογική σύζευξη, or λογική διάξευξη, not λογική άρνηση, xor λογική αποκλειστική διάζευξη. Παρακάτω θα δούμε αναλυτικά τα χαρακτηριστικά κάθε τύπου καθώς και το πώς μπορούν να χρησιμοποιηθούν μαζί με τελεστές για να προκύψουν εκφράσεις. 1.1 Ο τύπος integer Ο τύπος integer παριστάνει ακέραιους αριθμούς από το -32768 μέχρι και το 32767. Η ανάθεση άλλού τύπου τιμών σε ακέραιες μεταβλητές δεν επιτρέπεται. Δεν μπορεί κανείς δηλαδή να δηλώσει μία μεταβλητή a: integer και να της δώσει την τιμή 1.2, true ή 'c'. Ο μεταγλωττιστής μπορεί να εντοπίσει τέτοιου είδους λάθη και έτσι μπορούν να διορθωθούν πριν την εκτέλεση του προγράμματος. Είναι ευθύνη του προγραμματιστή όμως να ελέγχει ότι οι τιμές που αποθηκεύονται σε μία integer μεταβλητή είναι εντός ορίων, δηλαδή ανάμεσα στα -32768 και 32767. π.χ. οι εντολές του παραδείγματος 1 1 a := 256 * 64; writeln(a); 2 a := a * 2; writeln(a); τυπώνουν στην οθόνη το εξής: 16384-32768 Listing 1: Υπολογισμός εκτός ορίων Ο λόγος είναι ότι το 256 * 64 κάνει όντως 16384 αλλά το 16384 επί 2 κάνει 32768, τιμή που είναι εκτός ορίων. Με τις ακέραιες μεταβλητές δεν μπορούμε να χρησιμοποιήσουμε τον τελεστή διαίρεσης / ο οποίος στην Pascal δίνει πάντα αποτέλεσμα σε δεκαδική μορφή¹. Μεταξύ ακεραίων επιτρέπεται η χρήση του τελεστή ακέραιας διαίρεσης div ο οποίος επιστρέφει το ακέραιο πηλίκο μιας διαίρεσης. Αντίστοιχα ο τελεστής υπολοίπου mod επιστρέφει το υπόλοιπο της ακέραιας διαίρεσης. Υπενθυμίζουμε ότι για δύο ακέραιους αριθμούς a και b το πηλίκο c και το υπόλοιπο d της ακέραιας διαίρεσης του a με το b είναι τέτοια ώστε να ισχύει a = c b + d με το d τέτοιο ώστε 0 d < b. ¹ακόμα και σε εκφράσεις που έχουν ακέραιο αποτέλεσμα όπως π.χ. 4/2. 2
2 Ο τύπος real Οποτεδήποτε θέλουμε να πραγματοποιήσουμε υπολογισμούς με ποσότητες οι οποίες δεν είναι κατ' ανάγκη ακέραιες (π.χ. τιμές σε ευρώ, βάρη ανθρώπων σε κιλά κτλ.) ή είναι τέτοιες που οι υπολογισμοί με αυτές θα μπορούσαν να υπερβαίνουν τα όρια των integer πρέπει να χρησιμοποιήσουμε real. Με τις real μεταβλητές μπορούμε να χρησιμοποιήσουμε όλους τους αριθμητικούς τελεστές εκτός από τους mod και div. Η εσωτερική αναπαράσταση μίας μεταβλητής real είναι κινητής υποδιαστολής και έτσι τυπώνεται στην οθόνη ή και αλλού όταν ζητηθεί. Π.χ. το πρόγραμμα 2 τυπώνει 1 a := 42; writeln(a); 2 a := 420; writeln(a); Listing 2: Εκτύπωση real 4.20000000000000E+001 4.20000000000000E+002 Αν θέλουμε να αλλάξουμε αυτήν τη μορφή μπορούμε να γράψουμε ως όρισμα της writeln αντί για το όνομα της μεταβλητής, το όνομα της μεταβλητής ακολουθούμενο από έναν προσδιοριστή της μορφής :x ή :x:y. Στη δεύτερη περίπτωση, η σημασιολογία είναι ότι θέλουμε να εκτυπωθεί η μεταβλητή με y δεκαδικά ψηφία και τουλάχιστον x ψηφία στο σύνολο. Για παράδειγμα το πρόγραμμα 3 τυπώνει 1 a := 42; writeln(a:2:2); 2 a := 420; writeln(a:2:2); 3 a := 0.42; writeln(a:2:2); 4 a := 0.042; writeln(a:2:2); Listing 3: Εκτύπωση real 42.00 420.00 420.00 0.42 0.04 Σημειώστε ότι μπορούμε να δηλώσουμε αριθμητικές σταθερές κινητής υποδιαστολής και να τις αναθέσουμε σε real μεταβλητές είτε με το γνωστό τρόπο `ακέραιες μονάδες-υποδιαστολή-δεκαδικά ψηφία' π.χ. 42.25, 0.007 είτε σε μορφή `βάση-e-εκθέτης' π.χ. 12e47 που σημαίνει 12 10 47, 0.1e-12 που σημαίνει 0.1 10 12 κτλ. 3 Αριθμητικοί και συσχετιστικοί τελεστές σε integer και real Για να συνοψίσουμε σχετικά με τους αριθμητικούς τελεστές: Οι τελεστές +, - και * εφαρμόζονται τόσο σε integer όσο και real. Το αποτέλεσμα που δίνουν είναι integer αν και τα δύο ορίσματα είναι integer αλλιώς είναι real. Οι τελεστές div και mod εφαρμόζονται μόνο σε integer και δίνουν 3
αποτέλεσμα πάντα integer. Ο τελεστής / εφαρμόζεται και σε integer και σε real αλλά το αποτέλεσμά του είναι πάντα real. Οι τελεστές σύγκρισης μπορούν να εφαρμοστούν σε δύο integer ή real αλλά και μεταξύ ενός integer και ενός real. Το αποτέλεσμα που προκύπτει είναι μία λογική τιμή, true ή false. Χρειάζεται ιδιαίτερη προσοχή όταν συγκρίνουμε δύο μεταβλητές τύπου real. Γνωρίζουμε ότι η αναπαράσταση μη-ακέραιων αριθμών στην Pascal αλλά και στους υπολογιστές γενικότερα είναι εκείνη της κινητής υποδιαστολής. Το πλήθος των αριθμών που μπορούν να αναπαρασταθούν είναι πεπερασμένο. Οπότε προφανώς δεν μπορούμε να αναπαραστήσουμε σε έναν υπολογιστή ούτε καν τους ρητούς αριθμούς από το 0 μέχρι το 1 οι οποίοι είναι άπειροι. Οπότε πρακτικά οι αριθμοί στρογγυλεύονται σε κάποιον κοντινό τους με αρκετά μεγάλη ακρίβεια ώστε αυτό να μη δημιουργεί πρόβλημα στις περισσότερες εφαρμογές. Δείτε για παράδειγμα το παρακάτω πρόγραμμα: 1 program compare; 2 var 3 a, b, c: real; 4 begin 5 a := 100; 6 c := 100; 7 b := 1e-24; 8 a := a + b; 9 if a = c then 10 writeln('a equals c'); 11 end. Το πρόγραμμα δίνει στις μεταβλητές a και c την τιμή 100. Μετά προσθέτει στην a την τιμή 1 10 24 και στη συνέχεια ελέγχει αν οι δύο μεταβλητές είναι ίσες. Αν τρέξετε το πρόγραμμα θα δείτε ότι θεωρεί τις δύο μεταβλητές ίσες. Στην πράξη δεν πρέπει να χρησιμοποιούμε τον τελεστή = για να συγκρίνουμε μεταβλητές τύπου real παρόλο που αυτό είναι νόμιμο (και καλά κάνει και είναι) στην Pascal. Θα δούμε παρακάτω έναν πρακτικό τρόπο για να ελέγχουμε αν δύο αριθμοί είναι `ίσοι'. 4 Ο τύπος boolean Οι μεταβλητές τύπου boolean μπορούν να αναπαριστούν τις δύο τιμές της άλγεβρας Boole: true και false. Σε μεταβλητές αυτού του τύπου δεν μπορεί να χρησιμοποιηθεί κανένας από τους αριθμητικούς τελεστές. Μπορούν όμως να χρησιμοποιηθούν οι συσχετιστικοί τελεστές όπου θεωρείται ότι false < true. Οι αριθμητικοί τελεστές εφαρμόζονται σε αριθμητικές ποσότητες και δίνουν ως αποτέλεσμα νέες αριθμητικές ποσότητες. Με τον ίδιο τρόπο εφαρμόζονται και στις λογικές τιμές οι λογικοί τελεστές and (και, σύζευξη), or (ή, διάζευξη) και not (όχι, άρνηση). Τα αποτελέσματα είναι και αυτά λογικές τιμές. Οι πράξεις and και or παίρνουν δύο ορίσματα, ενώ η not μόνο ένα. Ορίζονται ως εξής: Το αποτέλεσμα της a and b είναι true αν και μόνο αν είναι true και το a και το b (αν δηλαδή έστω ένα από τα a ή b είναι false τότε και το αποτέλεσμα είναι false). Το αποτέλεσμα της a or b είναι false αν και μόνο αν και τα δύο ορίσματα είναι false (αν έστω και ένα είναι true τότε και το αποτέλεσμα είναι true). Το αποτέλεσμα της not a είναι το αντίθετο της τιμής a. Τα παραπάνω συνοψίζονται στον παρακάτω πίνακα αληθείας: 4
a b a and b a or b not a true true true true false true false false true false false true false true true false false false false true Θυμίζουμε ότι οι λογικές τιμές μπορούν να χρησιμοποιούνται όποτε το συντακτικό της Pascal αναμένει μία συνθήκη, δηλαδή στις εντολές if, repeat-until και while-do. 5 Ο τύπος char Οι μεταβλητές τύπου char μπορούν να αποθηκεύουν έναν και μόνο εκτυπώσιμο χαρακτήρα. Με τον ίδιο τρόπο που μπορούμε να δηλώσουμε μία μεταβλητή π.χ. τύπου integer και να της αναθέσουμε τιμή κάπως έτσι 1 var i: integer; 2 begin 3 i := 5; μπορούμε να δηλώσουμε μία μεταβλητή τύπου char και να της αναθέσουμε ως τιμή έναν χαρακτήρα, π.χ. κάπως έτσι: 1 var a: char; 2 begin 3 a := 'j'; Στο συγκεκριμένο παράδειγμα το όνομα της μεταβλητής είναι a και της ανατίθεται η τιμή 'j'. Αν τυπώσουμε τη μεταβλητή a του παραπάνω παραδείγματος με την εντολή writeln(a); στην οθόνη θα εμφανιστεί ο χαρακτήρας j (χωρίς εισαγωγικά). Τα μονά εισαγωγικά που χρησιμοποιήθηκαν στην εντολή ανάθεσης a := 'j' δεν είναι μέρος της τιμής της μεταβλητής αλλά χρησιμοποιούνται για να μπορέσει η Pascal να καταλάβει ότι πρόκειται για έναν χαρακτήρα και όχι για όνομα μεταβλητής. Αν δηλαδή λέγαμε απλώς a := j; τότε η Pascal θα θεωρούσε ότι θέλουμε να αναθέσουμε στη μεταβλητή a την τιμή της μεταβλητής j. Δείτε επίσης και το παράδειγμα που ακολουθεί: 1 program char1; 2 var 3 a,b: char; 4 begin 5 a := 'a'; 6 writeln('h metavliti a exei timn ', a); 7 b:= 'c'; 8 writeln('h metavliti v exei timn ', b); 9 end. Στις γραμμές 5 και 6 ανατίθεται η τιμή 'a' στη μεταβλητή a και στη συνέχεια τυπώνεται ένα μήνυμα 'H metavliti a exei timn ' και τέλος η τιμή της μεταβλητής a. Αυτό που πρέπει να γίνει κατανοητό είναι το όνομα της μεταβλητής, η τιμή που αυτή παίρνει και το μήνυμα που τυπώνεται 5
στην οθόνη είναι τρία διαφορετικά πράγματα. Στις γραμμές 6 και 7 έχουμε τη μεταβλητή b η οποία όμως παίρνει την τιμή 'c'. Στη γραμμή 7 κατά λάθος το μήνυμα που εκτυπώνεται είναι 'H metavliti v exei timn ' αντί για 'H metavliti b exei timn ' αλλά αυτό δεν επηρεάζει την εκτέλεση του προγράμματος γιατί πρόκειται απλώς για ένα μήνυμα το οποίο η Pascal δεν ερμηνεύει ούτε ελέγχει. Τελικά η έξοδος του παραπάνω προγράμματος είναι H metavliti a exei timn a H metavliti v exei timn c 6 Ενσωματωμένες (built-in) συναρτήσεις της Pascal Η Pascal παρέχει κάποιες έτοιμες συναρτήσεις στους προγραμματιστές ώστε να κάνει τη ζωή τους ευκολότερη. Οι συναρτήσεις αυτές δέχονται μία παράμετρο και επιστρέφουν μία τιμή. Στον πίνακα 1 αναγράφονται μερικές από αυτές (οι λεγόμενες αριθμητικές) και η λειτουργία που εκτελούν. Όλες δέχονται ως παραμέτρους τόσο real όσο και integer. Οι abs και sqr επιστρέφουν είτε real είτε integer ανάλογα με τον τύπο που τους δόθηκε ως παράμετρος. Όλες οι άλλες επιστρέφουν real. abs(x) sqr(x) sin(x) cos(x) exp(x) ln(x) sqrt(x) arctan(x) Πίνακας 1: Αριθμητικές συναρτήσεις Απόλυτη τιμή της ποσότητας x Το x στο τετράγωνο Ημίτονο του x Συνημίτονο του x Ο αριθμός e υψωμένος στη x-οστή δύναμη Φυσικός λογάριθμος του x Τετραγωνική ρίζα του x Τόξο εφαπτομένης του x Επίσης υπάρχουν και οι συναρτήσεις μεταφοράς trunc(x) και round(x). Αυτές δέχονται ορίσματα τύπου real και επιστρέφουν integer. Η πρώτη είναι η λεγόμενη συνάρτηση ακέραιου μέρους, δηλαδή επιστρέφει τον αριθμό που της δίνεται ως όρισμα χωρίς τα δεκαδικά ψηφία. Π.χ. η trunc(3.5) επιστρέφει 3, η trunc(2.9) επιστρέφει 2, η trunc(-3.7) επιστρέφει -3. Η δεύτερη στρογγυλεύει το όρισμά της στον πλησιέστερο ακέραιο. Π.χ. η round(3.7) επιστρέφει 4, η round(3.2) επιστρέφει 3 και η round(-3.7) επιστρέφει -4. Οι τιμές που είναι στη μέση στρογγυλεύονται προς το μεγαλύτερο ακέραιο κατ' απόλυτη τιμή, δηλαδή η round(3.5) επιστρέφει 4 και η round(-3.5) επιστρέφει -4. 6