Εισαγωγή στον Προγ/μό Η/Υ Ενότητα 3 Τύποι δεδομένων και μεταβλητών Διδάσκων: Μιχάλης Τίτσιας
Περιεχόμενα Τύποι δεδομένων Τελεστές Περισσότερα προγράμματα
Υπολογισμός όγκου για κύβο import acm.program.*; public class CubeVolume extends Program { public void run() { print("Όγκος κύβου πλευράς 5 = "); println(5*5*5); }
Υπολογισμός όγκου για κύβο import acm.program.*; public class CubeVolume extends Program { public void run() { print("Όγκος κύβου πλευράς 5 = "); println(5*5*5); } Το σύμβολο ; σηματοδοτεί το τέλος μιας εντολής
Υπολογισμός όγκου για κύβο import acm.program.*; public class CubeVolume extends Program { public void run() { print("Όγκος κύβου πλευράς 5 = "); println(5*5*5); } Έκφραση: περιγραφή υπολογισμού (εδώ 5*5*5) Κάθε έκφραση έχει μια τιμή (εδώ 125)
Αριθμητικές εκφράσεις και τελεστές 23+101 (τιμή = 123) -3*33 (τιμή = -99) 43-(-12) (τιμή = 55) 7/2 (ακέραιο πηλίκο, τιμή = 3 και όχι 3.5!!!) 7%2 (υπόλοιπο διαίρεσης 7/2, τιμή = 1) 14*5-(-4)%(15/4) (τιμή;)
Προτεραιότητα αριθμητικών τελεστών Πρώτα υπολογίζονται οι πράξεις *, /, % και μετά οι +, -. Ανάμεσα σε κάθε μία από τις δύο ομάδες, υπολογίζονται από τα αριστερά προς τα δεξιά όπως εμφανίζονται στην έκφραση. Π.χ.: 12/3*4 έχει τιμή 16 και όχι 1 Αν το 3*4 ήταν στον παρονομαστή θα έπρεπε να γράψουμε 12/(3*4)
Υπολογισμός όγκου για κύβο import acm.program.*; public class CubeVolume extends Program { public void run() { print("Όγκος κύβου πλευράς 5 = "); println(5*5*5); print(”σε κυβικά εκατοστά = ”); println(5*5*5*100*100*100); } Η τιμή της πλευράς εμφανίζεται 7 φορές: Υπολογισμοί για άλλο μήκος πλευράς απαιτούν 7 αλλαγές!
Υπολογισμός όγκου για κύβο import acm.program.*; public class CubeVolume extends Program { public void run() { print("Όγκος κύβου πλευράς 6 = "); println(5*5*5); print(”σε κυβικά εκατοστά = ”); println(5*5*5*100*100*100); } Η τιμή της πλευράς εμφανίζεται 7 φορές: Υπολογισμοί για άλλο μήκος πλευράς απαιτούν 7 αλλαγές!
Υπολογισμός όγκου για κύβο import acm.program.*; public class CubeVolume extends Program { public void run() { print("Όγκος κύβου πλευράς 6 = "); println(6*5*5); print(”σε κυβικά εκατοστά = ”); println(5*5*5*100*100*100); } Η τιμή της πλευράς εμφανίζεται 7 φορές: Υπολογισμοί για άλλο μήκος πλευράς απαιτούν 7 αλλαγές!
Υπολογισμός όγκου για κύβο import acm.program.*; public class CubeVolume extends Program { public void run() { print("Όγκος κύβου πλευράς 6 = "); println(6*6*5); print(”σε κυβικά εκατοστά = ”); println(5*5*5*100*100*100); } Η τιμή της πλευράς εμφανίζεται 7 φορές: Υπολογισμοί για άλλο μήκος πλευράς απαιτούν 7 αλλαγές!
Υπολογισμός όγκου για κύβο import acm.program.*; public class CubeVolume extends Program { public void run() { print("Όγκος κύβου πλευράς 6 = "); println(6*6*6); print(”σε κυβικά εκατοστά = ”); println(5*5*5*100*100*100); } Η τιμή της πλευράς εμφανίζεται 7 φορές: Υπολογισμοί για άλλο μήκος πλευράς απαιτούν 7 αλλαγές!
Υπολογισμός όγκου για κύβο import acm.program.*; public class CubeVolume extends Program { public void run() { print("Όγκος κύβου πλευράς 6 = "); println(6*6*6); print(”σε κυβικά εκατοστά = ”); println(6*6*6*100*100*100); } Η τιμή της πλευράς εμφανίζεται 7 φορές: Υπολογισμοί για άλλο μήκος πλευράς απαιτούν 7 αλλαγές!
Υπολογισμός όγκου για κύβο import acm.program.*; public class CubeVolume extends Program { public void run() { int x; // Δήλωση μεταβλητής για πλευρά x = 6; // Ανάθεση της τιμής 6 στο όνομα x print("Όγκος κύβου πλευράς 6 = "); println(x*x*x); print(”σε κυβικά εκατοστά = ”); println(x*x*x*100*100*100); } Η τιμή της πλευράς εμφανίζεται 2 φορές: Υπολογισμοί για άλλο μήκος πλευράς απαιτούν 2 αλλαγές!
Υπολογισμός όγκου για κύβο import acm.program.*; public class CubeVolume extends Program { public void run() { int x; // Δήλωση μεταβλητής για πλευρά x = 7; // Ανάθεση της τιμής 7 στο όνομα x print("Όγκος κύβου πλευράς 7 = "); println(x*x*x); print(”σε κυβικά εκατοστά = ”); println(x*x*x*100*100*100); } Η τιμή της πλευράς εμφανίζεται 2 φορές: Υπολογισμοί για άλλο μήκος πλευράς απαιτούν 2 αλλαγές!
Υπολογισμός όγκου για κύβο import acm.program.*; public class CubeVolume extends Program { public void run() { int x; // Δήλωση μεταβλητής για πλευρά x = 7; // Ανάθεση της τιμής 7 στο όνομα x print("Όγκος κύβου πλευράς 7 = "); println(x*x*x); print(”σε κυβικά εκατοστά = ”); println(x*x*x*100*100*100); } Ο υπολογισμός της τιμής του όγκου επαναλαμβάνεται ενώ έχει ήδη υπολογιστεί!
Υπολογισμός όγκου για κύβο import acm.program.*; public class CubeVolume extends Program { public void run() { int x; // Δήλωση μεταβλητής για πλευρά x = 7; // Ανάθεση της τιμής 7 στο όνομα x print("Όγκος κύβου πλευράς 7 = "); int ogkos = x*x*x; println(ogkos); print(”σε κυβικά εκατοστά = ”); println(ogkos*100*100*100); } Ο υπολογισμός της τιμής του όγκου γίνεται μία φορά. Όπου χρειάζεται η τιμή του χρησιμοποιείται η μεταβλητή ogkos - δεν επαναλαμβάνεται ο υπολογισμός.
Χρήση μεταβλητών για αναπαράσταση δεδομένων Με τη χρήση μεταβλητών επιτυγχάνουμε: Λιγότερες αλλαγές τιμών αν χρειαστούν Αποφυγή επανάληψης υπολογισμών χρησιμοποιώντας αποθηκευμένες τιμές Περισσότερο κατανοητά προγράμματα (χρήση ονομάτων αντί τιμών στους υπολογισμούς) Τυχαίο; Όχι: (απλή) εφαρμογή της αφαιρετικής αρχής
Χρήση μεταβλητών για αναπαράσταση δεδομένων Με τη χρήση μεταβλητών επιτυγχάνουμε: Λιγότερες αλλαγές τιμών αν χρειαστούν Αποφυγή επανάληψης υπολογισμών χρησιμοποιώντας αποθηκευμένες τιμές Περισσότερο κατανοητά προγράμματα (χρήση ονομάτων αντί τιμών στους υπολογισμούς) (Απλή) εφαρμογή της αφαιρετικής αρχής:
Χρήση μεταβλητών για αναπαράσταση δεδομένων αφαιρετική αρχή: Στα προγράμματά μας αναπαριστούμε τις γενικές (αφηρημένες) έννοιες και ιδέες που χρησιμοποιούνται στη λύση του προβλήματός μας και όχι μόνο κάποιες (συγκεκριμένες) τιμές. «Εργαλεία» αφαίρεσης: μεταβλητές, συναρτήσεις, αφηρημένοι τύποι δεδομένων, αντικείμενα. (Κάποια θα τα δούμε στη συνέχεια.)
Εφαρμογή της αφαιρετικής αρχής στο προηγούμενο πρόβλημα Πρόβλημα που λύσαμε: Υπολογισμός όγκου αν ξέρουμε την πλευρά, μετατροπή από κυβικά μέτρα σε κυβικά εκατοστά Σχετικές έννοιες: πλευρά, όγκος Ιδέα λύσης: όγκος = πλευρά×πλευρά×πλευρά, όγκος σε κυβ. εκατ. = όγκος×100×100×100
Εφαρμογή της αφαιρετικής αρχής στο προηγούμενο πρόβλημα Πρόβλημα που λύσαμε: Υπολογισμός όγκου αν ξέρουμε την πλευρά, μετατροπή από κυβικά μέτρα σε κυβικά εκατοστά Σχετικές έννοιες: πλευρά, όγκος Ιδέα λύσης: όγκος = πλευρά×πλευρά×πλευρά, όγκος σε κυβ. εκατ. = όγκος×100×100×100 x ogkos ogkos = x*x*x; ogkos*100*100*100
Σταθερές και μεταβλητές Όροι που εμφανίζονται στις εκφράσεις είναι οι σταθερές και οι μεταβλητές. Η τιμή μιας σταθεράς δεν αλλάζει ενώ μια μεταβλητή είναι ένα όνομα για μια τιμή που θα μπορεί να αλλάζει καθώς το πρόγραμμα τρέχει. Μια μεταβλητή στη Java είναι πιο εύκολα κατανοητή σαν ένα κουτί που μπορεί να αποθηκεύσει μια τιμή. Η μορφή μιας σταθεράς εξαρτάται από τον τύπο της: Ακέραιες σταθερές αποτελούνται από μια σειρά ψηφίων, προαιρετικά προηγείται με αρνητικό πρόσημο, όπως στα 0, 42, -1, ή 1000000. Οι κινητής υποδιαστολής περιλαμβάνουν μια υποδιαστολή όπως στο, 3.14159265 or 10.0. Μπορουν επίσης να εκφραστούν σε επιστημονική σημειογραφία με την προσθήκη του γράμματος E και ένα εκθέτη μετά τα ψηφία του αριθμού, έτσι ώστε το 5.646E-8 είναι το 5.646 x 10-8. Οι δύο σταθερές του τύπου boolean είναι true και false. Οι σταθερές χαρακτήρων και κειμένου θα αναλυθούν στο Κεφάλαιο 8. Προς το παρόν, το μόνο που χρειάζεται να ξέρετε είναι ότι μια σταθερά κειμένου αποτελείται από μια ακολουθία χαρακτήρων που περικλείονται σε διπλά εισαγωγικά, όπως το "hello, world". total 42 (Περιέχει έναν int) Κάθε μεταβλητή έχει τα ακόλουθα χαρακτηριστικά: Ένα όνομα, που διαφοροποιεί την μια μεταβλητή από την άλλη. Έναν τύπο, που καθορίζει τι μπορεί να περιέχει η μεταβλητή. Μια τιμή, που είναι το τρέχον περιεχόμενο της μεταβλητής Το όνομα και ο τύπος μιας μεταβλητής είναι σταθερά. Η τιμή αλλάζει κάθε φορά που θα ορίσετε μια νέα.
Δηλώσεις μεταβλητών Στην Java πρέπει να δηλώσετε μια μεταβλητή για να μπορέσετε να την χρησιμοποιήσετε. Η δήλωση καθορίζει το όνομα και τον τύπο της μεταβλητής και, στις περισσότερες περιπτώσεις, την αρχική τιμή. type name = value; Η πιο κοινή μορφή μιας δήλωσης μεταβλητών είναι όπου type είναι το όνομα ενός αρχέγονου τύπου ή μιας τάξης, name είναι το όνομα της μεταβλητής, και value είναι η αρχική τιμή της. Οι περισσότερες δηλώσεις εμφανίζονται κατά τον ορισμό μιας μεθόδου. Αυτές ονομάζονται τοπικές μεταβλητές και είναι προσβάσιμες μόνο εντός της μεθόδου. Οι μεταβλητές μπορεί να δηλωθούν και ως μέρος μιας τάξης. Αυτές ονομάζονται μεταβλητές στιγμιότυπου (θα τις δούμε σε λίγες εβδομάδες)
Μεταβλητή: όνομα,τιμή,τύπος int x; // Δήλωση μεταβλητής x int
Μεταβλητή: όνομα,τιμή,τύπος int x; // Δήλωση μεταβλητής x = 7; x int 7
Μεταβλητή: όνομα,τιμή,τύπος int x; // Δήλωση μεταβλητής x = 7; int y = 8; // Δήλωση με αρχικοποίηση x int 7 y int 8
Μεταβλητή: όνομα,τιμή,τύπος int x; // Δήλωση μεταβλητής x = 7; int y = 8; // Δήλωση με αρχικοποίηση y = x; // Η y παίρνει την τιμή της x x int 7 y int 7
Μεταβλητή: όνομα,τιμή,τύπος int x; // Δήλωση μεταβλητής x = 7; int y = 8; // Δήλωση με αρχικοποίηση y = x; // Η y παίρνει την τιμή της x y = 2*x+y/2-5; // Η y παίρνει την τιμή της έκφρασης x int 7 y int 12
Μεταβλητή: όνομα,τιμή,τύπος
Μεταβλητή: όνομα,τιμή,τύπος int x,y; // Δήλωση μεταβλητών x int y int
Μεταβλητή: όνομα,τιμή,τύπος int x,y; // Δήλωση μεταβλητών x = 7; x int 7 y int
Μεταβλητή: όνομα,τιμή,τύπος int x,y; // Δήλωση μεταβλητών x = 7; x = x+1; // Πρώτα υπολογίζεται η τιμή έκφρασης στα δεξιά, μετά η ανάθεση x int 8 y int
Μεταβλητή: όνομα,τιμή,τύπος int x,y; // Δήλωση μεταβλητών x = 7; x = x+1; // Πρώτα υπολογίζεται η τιμή έκφρασης στα δεξιά, μετά η ανάθεση x += 2; // Ίδιο με x = x+2; Υπάρχουν ακόμη -=, *=, /=, %= x int 10 y int
Μεταβλητή: όνομα,τιμή,τύπος int x,y; // Δήλωση μεταβλητών x = 7; x = x+1; // Πρώτα υπολογίζεται η τιμή έκφρασης στα δεξιά, μετά η ανάθεση x += 2; // Ίδιο με x = x+2; Υπάρχουν ακόμη -=, *=, /=, %= y = ++x; // Ίδιο με x = x+1; y = x; x int 11 y int 11
Μεταβλητή: όνομα,τιμή,τύπος int x,y; // Δήλωση μεταβλητών x = 7; x = x+1; // Πρώτα υπολογίζεται η τιμή έκφρασης στα δεξιά, μετά η ανάθεση x += 2; // Ίδιο με x = x+2; Υπάρχουν ακόμη -=, *=, /=, %= y = ++x; // Ίδιο με x = x+1; y = x; y = x++; // Ίδιο με y = x; x = x+1; x int 12 y int 11
Αναγνωριστικά στην Java Τα ονόματα μεταβλητών (και άλλων πραγμάτων) λέγονται αναγνωριστικά. Τα αναγνωριστικά ακολουθούν τους ακόλουθους κανόνες : Πρέπει να αρχίζουν με ένα γράμμα ή την κάτω παύλα . Οι άλλοι χαρακτήρες πρέπει να 'ναι γράμματα, ψηφία ή κάτω παύλες. Δεν πρέπει να είναι μία από τις δεσμευμένες λέξεις της Java: abstract boolean break byte case catch char class const continue default do double else extends false final finally float for goto if implements import instanceof int interface long native new null package private protected public return short static strictfp super switch synchronized this throw throws transient true try void volatile while πρέπει να κάνουν τον σκοπό τους προφανή στον αναγνώστη. πρέπει να τηρούν τις τυπικές συμβάσεις. Τα ονόματα των μεταβλητών, για παράδειγμα, θα πρέπει να αρχίζουν με μικρό γράμμα.
Λογικές Εκφράσεις στην Java class Add2Integers extends ConsoleProgram { public void run() { println("This program adds two numbers."); int n1 = readInt("Enter n1: "); int n2 = readInt("Enter n2: "); int total = n1 + n2; println("The total is " + total + "."); } n1 n2 total 17 25 42 Η κάρδια του προγράμματος Add2Integers είναι η γραμμή int total = n1 + n2; που πραγματοποιεί την πρόσθεση. Το n1 + n2 που υπάρχει στα δεξιά του ίσον είναι ένα παράδειγμα μιας έκφρασης, η οποία καθορίζει τις λειτουργίες που εμπλέκονται στον υπολογισμό. Μια έκφραση σε Java αποτελείται από όρους που ενώνονται μεταξύ τους με τελεστές. Κάθε όρος πρέπει να είναι ένα από τα ακόλουθα: Μια σταθερά(όπως το 3.14159265 ή το "hello, world") Το όνομα μιας μεταβλητής (όπως τα n1, n2, or total) Η κλήση μιας μεθόδου που επιστρέφει τιμές (όπως η readInt) Μια έκφραση που περικλείεται σε παρενθέσεις
Αρχέγονοι τύποι δεδομένων Παρότι οι πολύπλοκοι τύποι δεδομένων αναπαριστώνται με τη χρήση αντικειμένων, η Java ορίζει ένα σύνολο αρχέγονων τύπων για να διαχειριστεί απλά δεδομένα. Από τους οκτώ τέτοιους της Java, τα προγράμματα που θα φτιάξουμε έχουν μόνο τους ακόλουθους τέσσερις : int Αυτός ο τύπος χρησιμοποιείται για ακέραιους αριθμούς, όπως το 17 ή το -53. double Αυτός ο τύπος χρησιμοποιείται για αριθμούς που περιλαμβάνουν ένα δεκαδικό κλάσμα, όπως το 3,14159265. Στην Java, τέτοιες τιμές ονομάζονται αριθμοι κινητής υποδιαστολής. boolean Ο τύπος αυτός αφορά μια λογική τιμή (true or false). char Αυτός ο τύπος αντιπροσωπεύει ένα μόνο χαρακτήρα και θα του αφιερώσουμε ολόκληρη διάλεξη.
Περίληψη των βασικών τύπων Περίληψη των βασικών τύπων Ένας τύπος δεδομένων ορίζεται από ένα σύνολο τιμών που ονομάζονται domain (πεδίο τιμών) και μια σειρά πράξεων. Ο παρακάτω πίνακας δείχνει τα domains δεδομένων και κοινών πράξεων για τους οκτώ αρχέγονους (βασικούς) τύπους της Java: Type Domain Common operations Οι αριθμητικοί τελεστές: byte Ακέραιοι 8-bit με εύρος–128 to 127 + Πρόσθεση * Πολ/σμος - Αφαίρεση / Διαίρεση short Ακέραιοι 16-bit με εύρος -32768 to 32767 % Υπόλοιπο Ακέραιοι 32-bit με εύρος –2146483648 to 2146483647 Οι σχεσιακοί τελεστές: int = = Ίσο με != Όχι ισο Ακέραιοι 64-bit με εύρος –9223372036754775808 to 9223372036754775807 < μικρότερο <= Μικρότερο ίσο long > μεγαλύτερο >= Μεγαλύτερο ίσο αριθμούς κινητής υποδιαστολής 32-bit με εύρος ± 1.4 x 10-45 to ± 3.4028235 x 10-38 float Οι αριθμητικοί τελεστές εκτός του % αριθμούς κινητής υποδιαστολής 64-bit με εύρος ± 4.39 x 10-322 to ± 1.7976931348623157 x 10308 Οι σχεσιακοί τελεστές double char 16-bit χαρακτήρες κωδικοποιημένοι με Unicode Οι σχεσιακοί τελεστές Οι λογικοί τελεστές: boolean οι τιμές true και false && και || ή ! οχι
Τελεστές και τελεστέοι Στην Java (και στις περισσότερες γλώσσες ) οι υπολογισμοί έχουν την μορφή αριθμητικών εκφράσεων που μοιάζουν με εκφράσεις από τα μαθηματικά.. Οι πιο κοινοί τελεστές της Java είναι αυτοί για τους αριθμητικούς υπολογισμούς : + Πρόσθεση – Αφαίρεση * Πολλαπλασιασμός / Διαίρεση % Υπόλοιπο Οι τελεστές στην Java συνήθως εμφανίζονται μεταξύ δύο υποεκφράσεων, που ονομάζονται τελεστεοι. Οι τελεστές που έχουν δύο τελεστέους ονομάζονται δυαδικοί τελεστές. Ο τελεστής - μπορεί να εμφανιστεί ως μοναδιαίος τελεστής, όπως στην έκφραση –x, που εκφράζει το αρνητικό του x.
Υπερχείλιση τιμής int x; x = 7; print("Όγκος κύβου πλευράς 7 = "); import acm.program.*; public class test1 extends Program { public void run() { int x; x = 7; print("Όγκος κύβου πλευράς 7 = "); int ogkos = x*x*x; println(ogkos); print(”σε κυβικά εκατοστά = ”); println(ogkos*100*100*100); print(”σε κυβικά χιλιοστά = ”); println(ogkos*1000*1000*1000); }
Υπερχείλιση τιμής int x; x = 7; print("Όγκος κύβου πλευράς 7 = "); import acm.program.*; public class test1 extends Program { public void run() { int x; x = 7; print("Όγκος κύβου πλευράς 7 = "); int ogkos = x*x*x; println(ogkos); // εμφανίζει 343 print(”σε κυβικά εκατοστά = ”); println(ogkos*100*100*100); // εμφανίζει 343000000 print(”σε κυβικά χιλιοστά = ”); println(ogkos*1000*1000*1000); // εμφανίζει -597383680 }
Υπερχείλιση τιμής int x; x = 7; print("Όγκος κύβου πλευράς 7 = "); import acm.program.*; public class test1 extends Program { public void run() { int x; x = 7; print("Όγκος κύβου πλευράς 7 = "); int ogkos = x*x*x; println(ogkos); // εμφανίζει 343 print(”σε κυβικά εκατοστά = ”); println(ogkos*100*100*100); // εμφανίζει 343000000 print(”σε κυβικά χιλιοστά = ”); println(ogkos*1000*1000*1000); // εμφανίζει -597383680 } ΛΑΘΟΣ ΥΠΟΛΟΓΙΣΜΟΣ!
Υπερχείλιση Ο αριθμός 343000000000 είναι πολύ μεγάλος για να αναπαρασταθεί ως ακέραιος της Java (int). Στη Java οι αριθμοί εκτός από την τιμή τους έχουν και τον τύπο τους. Ο τύπος ενός αριθμού κυρίως καθορίζει: Πόσα bytes στη μνήμη χρησιμοποιούνται για την κωδικοποίηση της τιμής του Οι ακέραιοι της Java (int) χρησιμοποιούν 4 bytes Για τον 343000000000 θα πρέπει να χρησιμοποιήσουμε μεγάλους ακέραιους της Java, δηλ. τον τύπο long
Τύποι ακεραίων της Java 127 -128 32767 -32768 2147483647 -2147483648 9223372036854775807 -9223372036854775808
Υπερχείλιση long x; x = 7; print("Όγκος κύβου πλευράς 7 = "); import acm.program.*; public class test1 extends Program { public void run() { long x; x = 7; print("Όγκος κύβου πλευράς 7 = "); long ogkos = x*x*x; println(ogkos); // εμφανίζει 343 print(”σε κυβικά εκατοστά = ”); println(ogkos*100*100*100); // εμφανίζει 343000000 print(”σε κυβικά χιλιοστά = ”); println(ogkos*1000*1000*1000); // εμφανίζει 343000000000 }
Οι τιμές και οι τύποι τους Οι τιμές που μπορούν να παρασταθούν από τον τύπο int μπορούν να παρασταθούν και από long. Η τιμή 123 έχει τύπο int Πως μπορώ να έχω την τιμή 123 με τύπο long;
Οι τιμές και οι τύποι τους Οι τιμές που μπορούν να παρασταθούν από τον τύπο int μπορούν να παρασταθούν και από long. Η τιμή 123 έχει τύπο int Πως μπορώ να έχω την τιμή 123 με τύπο long; Απάντηση: 123L ή 123l ή (long) 123 Π.χ., println(123L*1000000000L);
Οι τιμές και οι τύποι τους Μπορούμε να έχουμε εκφράσεις με τιμές από διαφορετικούς τύπους; Π.χ., 100*3L Απάντηση: Ναι, πριν υπολογιστεί η τιμή της έκφρασης, οι τύποι όλων των τελεστέων αυτόματα μετατρέπονται στον «μεγαλύτερο» τύπο που συμμετέχει στην έκφραση. Κατόπιν υπολογίζεται η τιμή της έκφρασης Δηλαδή 100*3L → 100L*3L → 300L
Παράδειγμα println(3*1000000000); // Εμφανίζει -1294967296 } import acm.program.*; public class test1 extends Program { public void run() { println(3*1000000000); // Εμφανίζει -1294967296 } println(3L*1000000000L); //Εμφανίζει 3000000000
Παράδειγμα println(3*1000000000); // Εμφανίζει -1294967296 } import acm.program.*; public class test1 extends Program { public void run() { println(3*1000000000); // Εμφανίζει -1294967296 } println(3L*1000000000); // Εμφανίζει 3000000000
Παράδειγμα println(3*1000000000); // Εμφανίζει -1294967296 } import acm.program.*; public class test1 extends Program { public void run() { println(3*1000000000); // Εμφανίζει -1294967296 } println(3*1000000000L); // Εμφανίζει 3000000000
Ανάθεση τιμών μεταξύ διαφορετικών τύπων import acm.program.*; public class test1 extends Program { public void run() { long x; x = 7; print("Όγκος κύβου πλευράς 7 = "); long ogkos = x*x*x; println(ogkos); // εμφανίζει 343 print(”σε κυβικά εκατοστά = ”); println(ogkos*100*100*100); // εμφανίζει 343000000 print(”σε κυβικά χιλιοστά = ”); println(ogkos*1000*1000*1000); // εμφανίζει 343000000000 } long long Σωστή ανάθεση μιας και τύπος στα αριστερά = τύπος δεξιά
Ανάθεση τιμών μεταξύ διαφορετικών τύπων import acm.program.*; public class test1 extends Program { public void run() { long x; x = 7; print("Όγκος κύβου πλευράς 7 = "); int ogkos = x*x*x; println(ogkos); // εμφανίζει 343 print(”σε κυβικά εκατοστά = ”); println(ogkos*100*100*100); // εμφανίζει 343000000 print(”σε κυβικά χιλιοστά = ”); println(ogkos*1000*1000*1000); // εμφανίζει 343000000000 } int long Λάθος ανάθεση μιας και τύπος στα αριστερά < τύπος δεξιά
Ανάθεση τιμών μεταξύ διαφορετικών τύπων import acm.program.*; public class test1 extends Program { public void run() { int x; x = 7; print("Όγκος κύβου πλευράς 7 = "); long ogkos = x*x*x; println(ogkos); // εμφανίζει 343 print(”σε κυβικά εκατοστά = ”); println(ogkos*100*100*100); // εμφανίζει 343000000 print(”σε κυβικά χιλιοστά = ”); println(ogkos*1000*1000*1000); // εμφανίζει 343000000000 } long int Σωστή ανάθεση μιας και τύπος στα αριστερά > τύπος δεξιά
Μεταβλητές Δήλωση μεταβλητής οποιουδήποτε τύπου: τύπος όνομα; // Δήλωση τύπος όνομα = τιμή; //Δήλωση με ανάθεση τιμής όνομα τύπος τιμή
Μεταβλητές Δήλωση μεταβλητής οποιουδήποτε τύπου: τύπος όνομα; // Δήλωση τύπος όνομα = τιμή; //Δήλωση με ανάθεση τιμής Π.χ.: long x = 11L; όνομα τύπος τιμή x long 11L
Μεταβλητές Δήλωση μεταβλητής οποιουδήποτε τύπου: τύπος όνομα; // Δήλωση τύπος όνομα = τιμή; //Δήλωση με ανάθεση τιμής x = 11L;// Δεν επιτρέπεται η χρήση πρίν τη δήλωση long x; όνομα τύπος τιμή
Μεταβλητές Δήλωση μεταβλητής οποιουδήποτε τύπου: τύπος όνομα; // Δήλωση τύπος όνομα = τιμή; //Δήλωση με ανάθεση τιμής x = 11L;// Δεν επιτρέπεται η χρήση πρίν τη δήλωση long x; x = 11L; όνομα τύπος τιμή
Βασικοί τύποι & Τιμές public void run() { double x; /* Δήλωση μεταβλητής κινητής υποδιαστολής διπλής ακρίβειας 8 bytes */ x = 19.99; double y = -0.01; x = x-y+23E-4; // ίδιο με 23×10-4, δηλαδή x-y+0.0023 x = 15; // ίδιο με x = 15.0; x = 15/2; println(x); // εμφανίζει 7.0 println(15/2.0); // εμφανίζει 7.5 }
Αριθμοί κινητής υποδιαστολής Δεν αναπαρίστανται όλοι οι αριθμοί Διαφορετικά κενά μεταξύ αριθμών Ασυνέπεια πράξεων: println((1E+10+0.1)-1E+10); // 0.10000038146972656 println((1E+20+0.01)-1E+20); // 0.0
Βασικοί τύποι & Τιμές public void run() { float x; /* Δήλωση μεταβλητής κινητής υποδιαστολής απλής ακριβειας (4 bytes)*/ x = 19E-10f; // ή 19E-10F ή 19e-10F double y = x; // ok αφού τύπος double > float x = 15; // ίδιο με x = 15.0F; x = 15/2; // Πρώτα υπολογίζεται έκφραση δεξιά println(x); // εμφανίζει 7.0 println(15/2.0); // εμφανίζει 7.5 }
Μετατροπές short s = 39; int x; x = s; // ok s short 39 x int 39
Μετατροπές short s = 39; int x; x = s; // ok s = x; //Δεν επιτρέπεται από τον μεταγλωττιστή! // Αυστηρός έλεγχος τύπων s short 39 x int 39
Μετατροπές short s = 39; int x; x = s; // ok s = x; s = (short) x; // ok // Μπορεί να χαθεί πληροφορία s short 39 x int 39
Μετατροπές short s = 39; int x; x = s; // ok s = x; s = (short) x; // ok (καλούπωμα) // Μπορεί να χαθεί πληροφορία s short 39 x int 39 Επιτρέπονται: char ↔ short → int → long → float → double
Boolean Εκφράσεις Ο πιο σημαντικός αρχέγονος τύπος στη Java είναι ο boolean, ακόμα κι αν είναι ο πιο απλός. Οι μόνες τιμές του είναι το αληθινό (true) και το ψεύτικο (false), αλλά αυτά είναι ακριβώς οι τιμές που χρειάζεστε, αν θέλετε το πρόγραμμά σας να παίρνει αποφάσεις. Το όνομα boolean προέρχεται από τον Άγγλο μαθηματικό George Boole ο οποίος το 1854 έγραψε ένα βιβλίο με τίτλο «Μια έρευνα σχετικά με τους νόμους της σκέψης, επί των οποίων βασίζονται οι μαθηματικές θεωρίες της λογικής και των πιθανοτήτων». Αυτό το βιβλίο παρουσιάζει ένα σύστημα της λογικής που έχει γίνει γνωστή ως άλγεβρα Boole, η οποία αποτελεί το θεμέλιο για τον τύπο δεδομένων boolean. George Boole (1791-1871)
Λογικές τιμές και ο τύπος boolean double temp = readDouble(”Θερμοκρασία:”); println(temp*9/5+32); // Αριθμητική έκφραση (μετατροπή σε Fahrenheit)
Λογικές τιμές και ο τύπος boolean double temp = readDouble(”Θερμοκρασία:”); println(temp*9/5+32); // Αριθμητική έκφραση (μετατροπή σε Fahrenheit) println(temp > 40.0); // Λογική έκφραση (τιμή Αλήθεια –true- ή Ψέμα –false-) // Εμφανίζει true εάν temp>40.0, αν όχι, false
Λογικές τιμές και ο τύπος boolean double temp = readDouble(”Θερμοκρασία:”); println(temp*9/5+32); // Αριθμητική έκφραση (μετατροπή σε Fahrenheit) boolean kauswnas; // Μεταβλητή τύπου boolean για αναπαράσταση τιμών true και false kauswnas = temp > 40.0; println(kauswnas); // Εμφανίζει true false
Λογικές τιμές και ο τύπος boolean double temp = readDouble(”Θερμοκρασία:”); boolean metrios = 10 <= temp < 40.0; //Λάθος σύνταξη boolean metrios = 10 <= temp && temp>40.0; boolean akraios = temp < 0 || temp > 42.0; boolean oxi_metrios = !metrios;
Boolean Τελεστές Οι τελεστές που χρησιμοποιούνται με τον boolean τύπο δεδομένων χωρίζονται σε δύο κατηγορίες: σχεσιακούς τελεστές και λογικούς τελεστές. Υπάρχουν έξι σχεσιακοί τελεστές, που συγκρίνουν τις τιμές άλλων τύπων και παράγουν ένα boolean αποτέλεσμα: = = Ίσο με < Μικρότερο από != Όχι ίσο <= Μικρότερο ή ίσο από >= Μεγαλύτερο ή ίσο από > Μεγαλύτερο από π.χ. Η έκφραση Ν <= 10 έχει τιμή true αν το Ν είναι μικρότερο ή ίσο του 10 και τιμή false αλλιώς. p || q σημαίνει p ή q (ή και τα 2) Υπάρχουν επίσης τρεις λογικοί τελεστές : && Λογικό AND || Λογικό OR ! Λογικό NOT p && q σημαίνει μαζί p και q !p σημαίνει το αντίθετο του p
Δίσεκτο έτος; public void run() { int year; year = readInt(”Δώσε έτος:”); print(”Το έτος ”+year+”είναι δίσεκτο: ”); boolean isleap; isleap = ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0 ); println(isleap); }
Σημειώσεις επί των τελεστών Boolean Να θυμάστε ότι η Java χρησιμοποιεί = για να υποδηλώσει ανάθεση. Για να ελέγξετε αν δύο τιμές είναι ίσες, θα πρέπει να χρησιμοποιήσετε τον τελεστή ==. Στην Java δεν μπορείτε να χρησιμοποιήσετε περισσότερους από ένα σχεσιακό τελεστή σε μια σύγκριση, όπως γίνεται στα μαθηματικά. Για να εκφράσετε την μαθηματική έκφραση 0 ≤ x ≤ 9 0 <= x && x <= 9 θα πρέπει να κάνετε και τις δύο συγκρίσεις ρητά Ο τελεστής || σημαίνει το ένα από τα δυο ή και τα δυο, που δεν είναι σαφές από την ελληνική απόδοση «ή» Προσοχή χρειάζεται όταν συνδυάζετε τον τελεστή ! με τους && και || (κανόνες De Morgan).
Διαίρεση και καλούπωμα Όταν ένας δυαδικός τελεστής εφαρμόζεται σε αριθμητικές τιμές, το αποτέλεσμα είναι τύπου int, αν και οι δύο είναι τύπου int, αλλά double, αν ένας από αυτούς είναι double. Ο κανόνας αυτός έχει σημαντικές συνέπειες στην περίπτωση της διαίρεσης. Για παράδειγμα, η έκφραση 14 / 5 θα έπρεπε να δίνει τιμή 2.8, αλλά αφού και οι δύο τελεστέοι είναι τύπου int, η Java υπολογίζει το ακέραιο αποτέλεσμα χωρίς κλασματικό μέρος. Το αποτέλεσμα επομένως είναι 2. Αν θέλετε ένα μαθηματικά σωστό αποτέλεσμα, θα πρέπει να μετατρέψετε τουλάχιστον ένα τελεστέο σε double, π.χ. (double) 14 / 5 Η μετατροπή επιτυγχάνεται με τη βοήθεια ενός καλουπώματος, που αποτελείται από ένα όνομα τύπου σε παρένθεση.
Οι παγίδες της διαίρεσης Εξετάστε τις ακόλουθες δηλώσεις Java, που προορίζονται για τη μετατροπή 100˚ Κελσίου σε Φαρενάιτ: double c = 100; double f = 9 / 5 * c + 32; Ο υπολογισμός συνίσταται στην αποτίμηση της έκφρασης : 9 / 5 * c + 32 Το πρόβλημα ανακύπτει από το γεγονός ότι τα 9 και 5 είναι τύπου int, που σημαίνει ότι το αποτέλεσμα είναι int. 1 100 132 9 / 5 * c + 32
Οι παγίδες της διαίρεσης Μπορείτε να διορθώσετε αυτό το πρόβλημα με τη μετατροπή του κλάσματος σε double, είτε με την εισαγωγή υποδιαστολών ή χρησιμοποιώντας καλούπωμα: double c = 100; double f = (double) 9 / 5 * c + 32; Ο υπολογισμός μοιάζει τώρα έτσι: 1.8 180.0 212.0 (double) 9 / 5 * c + 32 9.0
Ο Τελετής Υπολοίπου Ο μόνος αριθμητικός τελεστής που δεν έχει αντίστοιχο στα μαθηματικά είναι το %, και εφαρμόζεται μόνο σε ακέραιους τελεστέους και υπολογίζει το υπόλοιπο όταν ο πρώτος διαιρείται με τον δεύτερο : 14 % 5 returns 4 14 % 7 7 % 14 7 Το αποτέλεσμα του % έχει εμπειρικό νόημα μόνο αν και οι δύο τελεστέοι είναι θετικοί. Ο τελεστής υπόλοιπου αποδεικνύεται χρήσιμος σε ένα εκπληκτικό αριθμό προγραμματιστικών εφαρμογών και αξίζει μελέτης..
μοναδιαίο - (καλούπωμα) Προτεραιότητα Εάν μια έκφραση περιέχει περισσότερα από ένα τελεστή, η Java χρησιμοποιεί κανόνες προτεραιότητας για να καθορίσει τη σειρά της αξιολόγησης. Οι αριθμητικοί τελεστές έχουν την ακόλουθη προτεραιότητα: Υψηλό μοναδιαίο - (καλούπωμα) * / % + - Χαμηλό Έτσι, Java αξιολογεί πρώτα το μοναδιαίο - και τα καλουπώματα, μετά τα * , / και %, και τέλος τα + και -. Η προτεραιότητα ισχύει μόνο όταν δύο τελεστέοι ανταγωνίζονται για τον ίδιο τελεστή. Εάν οι τελεστές ανεξάρτητοι, Java υπολογίζει από τα αριστερά προς τα δεξιά. Οι παρενθέσεις μπορούν να χρησιμοποιηθούν για να αλλάξετε τη σειρά των πράξεων.
Άσκηση: Προτεραιότητα Ποια είναι η τιμή της έκφρασης στο κάτω μέρος της οθόνης; 42 32 32 4 3 30 8 ( 1 + 2 ) % 3 * 4 + 5 * 6 / 7 * ( 8 % 9 ) + 10
Εντολές εκχώρησης Μπορείτε να αλλάξετε την τιμή μιας μεταβλητής στο πρόγραμμά σας, χρησιμοποιώντας μια εντολή εκχώρησης, η οποία έχει τη γενική μορφή: variable = expression; Το αποτελεσμα μιας εντολής εκχώρησης είναι να υπολογιστεί η τιμή της έκφρασης στη δεξιά πλευρά του ίσον και να οριστεί αυτή η τιμή στη μεταβλητή που εμφανίζεται στην αριστερή πλευρά. Έτσι, η δήλωση εκχώρησης total = total + value; Προσθέτει τις τρέχουσες τιμές των total και value και στη συνέχεια αποθηκεύει το σύνολο στη μεταβλητή total. Όταν εκχωρείτε μια νέα τιμή σε μια μεταβλητή, η παλαιά τιμή αυτής της μεταβλητής χάνεται.
Στενογραφικές Εκχωρήσεις Δηλώσεις όπως η total = total + value; είναι τόσο κοινές που η Java επιτρέπει την ακόλουθη μορφή total += value; variable op= expression; Η γενική μορφή μιας στενογραφικής εκχώρησης είναι όπου op είναι οποιοσδήποτε δυαδικός τελετής της Java. Το αποτέλεσμα αυτής της είναι η ίδιο με της variable = variable op (expression); π.χ. η ακόλουθη δήλωση πολλαπλασιάζει το salary με το 2. salary *= 2;
Τελεστές αύξησης και μείωσης Μια άλλη σημαντική μορφή στενογραφίας που εμφανίζεται συχνά στη Java είναι ο τελεστής προσαύξησης, ο οποίος πιο συχνά εμφανίζεται αμέσως μετά από μια μεταβλητή : x++; Αποτέλεσμα αυτής της δήλωσης είναι να προσθέσει ένα στην τιμή του x, που σημαίνει ότι είναι ισοδύναμη με την x += 1; ή σε ακόμα μακρύτερη μορφή x = x + 1; Ο τελεστής -- (που ονομάζεται τελεστής απομείωσης) είναι παρόμοιος, αλλά αφαιρεί ένα αντί να προσθέτει. Και ο ++ και ο -- είναι πιο περίπλοκοι από ό, τι φαίνεται εδώ.
Σύνοψη Τελεστών Ενός ορίσματος: +x, -x, ++x, --x, x++, x--, !x
Σύνοψη Τελεστών Ενός ορίσματος: +x, -x, ++x, --x, x++, x--, !x Δύο ορισμάτων: x+y, x-y, x*y, x/y, x%y, x&&y, x||y
Σύνοψη Τελεστών Ενός ορίσματος: +x, -x, ++x, --x, x++, x--, !x Δύο ορισμάτων: x+y, x-y, x*y, x/y, x%y, x&&y, x||y Εκχωρήσεις: x = y, x += y, x -= y, x *= y, x /= y, x %= y
Σύνοψη Τελεστών Ενός ορίσματος: +x, -x, ++x, --x, x++, x--, !x Δύο ορισμάτων: x+y, x-y, x*y, x/y, x%y, x&&y, x||y Εκχωρήσεις: x = y, x += y, x -= y, x *= y, x /= y, x %= y Συγκρίσεις: x==y, x<y, x>y, x<=y, x>=y, x!=y
Σύνοψη Τελεστών Ενός ορίσματος: +x, -x, ++x, --x, x++, x--, !x Δύο ορισμάτων: x+y, x-y, x*y, x/y, x%y, x&&y, x||y Εκχωρήσεις: x = y, x += y, x -= y, x *= y, x/=y,x %= y Συγκρίσεις: x==y, x<y, x>y, x<=y, x>=y, x!=y Προτεραιότητα τελεστών: {*, /, %}, {+, -}, συγκρίσεις, λογικές πράξεις, εκχωρήσεις. Μεταξύ ίδιας προτεραιότητας, προηγούνται οι από αριστερά πράξεις: x+y-z == (x+y)-z. (Εκτός εκχωρήσεων.)
Γρήγορη Αξιολόγηση Η Java αξιολογεί τους τελεστές && και | | χρησιμοποιώντας μια στρατηγική που ονομάζεται short-circuit με τον οποίο αξιολογεί τον τελεστή στα δεξιά μόνο αν χρειάζεται να το πράξει. Για παράδειγμα, αν το n είναι 0, ο δεξιά τελεστής && στο n != 0 && x % n == 0 δεν αξιολογείται καν μια και ο n != 0 είναι false. Γιατί η έκφραση false && anything είναι πάντα false, η υπόλοιπη έκφραση δεν έχει σημασία! Ένα από τα πλεονεκτήματα της αξιολόγησης short-circuit είναι ότι μπορείτε να χρησιμοποιήσετε τους && and || για να προλάβετε λάθη κατά την εκτέλεση. Αν στο παράδειγμα το n ήταν 0, η αξιολόγηση του x % n θα επέφερε ένα σφάλμα “διαίρεση με το 0”.
Ασκήσεις μελέτης Γράψε ένα πρόγραμμα που θα διαβάζει ένα υπόλοιπο λογαριασμού και επίσης ένα ετήσιο επιτόκιο εκφρασμένο ως ποσοστό επί τοις εκατό. Έπειτα το πρόγραμμα θα τυπώνει το νέο υπόλοιπο μετά από ένα χρόνο (υποθέτοντας ότι δεν υπάρχουν καταθέσεις ή αναλήψεις κατά την διάρκεια του χρόνου) . Γράψε ένα πρόγραμμα που θα διαβάζει ένα θετικό ακέραιο αριθμό, θα υπολογίζει τον αμέσως (αυστηρώς) μεγαλύτερο ακέραιο που διαιρείται ακριβώς με το 7 και θα τον τυπώνει. Επίσης θα υπολογίζει αν ο αρχικός ακέραιος που δόθηκε διαιρείται ακριβώς με το 7 ή όχι και θα τυπώνει την αντίστοιχη λογική τιμή. Π.χ. μια εκτέλεση του προγράμματος θα μπορούσε να έχει την εξής έξοδο Give an integer: 48 The number larger than 48 that is divided exactly by 7 is 49 48 is divided by 7: false
Διάβασμα για το σπίτι Κεφάλαιο 3 από «Η Τέχνη και Επιστήμη της JAVA: Μια εισαγωγή στην Επιστήμη των Υπολογιστών», E. Roberts