Κατέβασμα παρουσίασης
Η παρουσίαση φορτώνεται. Παρακαλείστε να περιμένετε
ΔημοσίευσεΓῆ Στεφανόπουλος Τροποποιήθηκε πριν 8 χρόνια
1
Εισαγωγή στον Προγ/μό Η/Υ Ενότητα 6 Mέθοδοι και τεχνικές προγραμματισμού Διδάσκων: Μιχάλης Τίτσιας
2
Περιεχόμενα 5.1 Μια γρήγορη επισκόπηση των μεθόδων 5.2 Γράφοντας τις δικές σας μεθόδους 5.3 Η διαδικασία πίσω από την κλήση μιας μεθόδου 5.4 Αποσύνθεση 5.5 Αλγοριθμικές μέθοδοι
3
Μια γρήγορη επισκόπηση των μεθόδων Έχετε εργαστεί με μεθόδους από το πρώτο σας πρόγραμμα Java στο κεφάλαιο 2. Η μέθοδος run σε κάθε πρόγραμμα είναι ένα μόνο παράδειγμα. Τα περισσότερα από τα προγράμματα που έχετε δει, έχουν χρησιμοποιήσει και άλλες μεθόδους, όπως println και setColor. Στο βασικό επίπεδο, μια μέθοδος είναι μια σειρά από εντολές που έχουν γκρουπαριστεί μαζί και έχουν πάρει ένα όνομα. Το όνομα σας δίνει τη δυνατότητα να εκτελείτε τις εντολές πολύ εύκολα. Αντί της αντιγραφής ολόκληρης της λίστας εντολών, μπορείτε να παρέχετε μόνο το όνομα της μεθόδου. Χρήσιμοι όροι για όσους μαθαίνουν μεθόδους: –Η χρήση του ονόματος μιας μεθόδου είναι γνωστή ως κλήση της μεθόδου –Ο προγραμματιστής μπορεί να περνά πληροφορίες μέσω ορισμάτων. –Όταν μια μέθοδος ολοκληρωθεί, επιστρέφει στον καλούντα της. –Μια μέθοδος μπορεί να περάσει πληροφορίες στον καλούντα επιστρέφοντας ένα αποτέλεσμα.
4
Μέθοδοι και απόκρυψη πληροφορίας Ένα από τα πιο σημαντικά πλεονεκτήματα των μεθόδων είναι ότι καθιστούν δυνατό στους χρήστες να αγνοούν τις εσωτερικές λειτουργίες πολύπλοκων εργασιών. Όταν χρησιμοποιείτε μια μέθοδο, είναι πιο σημαντικό να γνωρίζετε τι κάνει η μέθοδος από το να καταλάβετε ακριβώς πώς λειτουργεί. Οι λεπτομέρειες έχουν ενδιαφέρον μόνο για τον προγραμματιστή που γράφει την μέθοδο. Οι προγραμματιστές που χρησιμοποιούν τη μέθοδο ως εργαλείο μπορούν συνήθως αγνοούν εντελώς τις λεπτομέρειες. Η ιδέα ότι οι χρήστες θα πρέπει να είναι απομονωμένοι από τις λεπτομέρειες της λειτουργίας της μεθόδου είναι η αρχή της απόκρυψης πληροφορίας, η οποία αποτελεί έναν από τους ακρογωνιαίους λίθους της μηχανικής λογισμικού.
5
Μέθοδοι ως εργαλεία για προγραμματιστές Ιδιαίτερα οταν πρωτομαθαίνετε προγραμματισμό, είναι σημαντικό να έχετε κατά νου ότι οι μέθοδοι δεν είναι το ίδιο με τις εφαρμογές, αν και τα δύο παρέχουν μια υπηρεσία, να κρύβουν την υποκείμενη πολυπλοκότητα του υπολογισμού. Η βασική διαφορά είναι ότι ένα πρόγραμμα παρέχει μια υπηρεσία σε έναν χρήστη, ο οποίος συνήθως δεν είναι προγραμματιστής, αλλά κάποιος που τυχαίνει να κάθεται μπροστά από τον υπολογιστή. Αντίθετα, η μέθοδος παρέχει μια υπηρεσία σε έναν προγραμματιστή, ο οποίος δημιουργεί συνήθως κάποιο είδος της εφαρμογής. Η διάκριση αυτή είναι ιδιαίτερα σημαντική όταν προσπαθείτε να καταλάβετε πώς οι έννοιες της εισόδου και εξόδου σε ένα πρόγραμμα διαφέρουν από τις έννοιες των ορισμάτων και των αποτελεσμάτων σε μια μέθοδο. Μέθοδοι όπως readInt και println χρησιμοποιείται για την επικοινωνία με το χρήστη και δεν παίζουν κανένα ρόλο στην ροή πληροφορίας από το ένα μέρος ενός προγράμματος σε ένα άλλο.
6
Οι κλήσεις μεθόδων ως εκφράσεις Συντακτικά, οι κλήσεις μεθόδων στην Java αποτελούν μέρος του πλαισίου έκφρασης. Όσες επιστρέφουν τιμή μπορούν να είναι όροι μιας έκφρασης όπως οι μεταβλητές και σταθερές Η ταξη Math του πακέτου java.lang ορίζει αρκετές μεθόδους που είναι χρήσιμες στην γραφή μαθηματικών εκφράσεων. Υποθέστε, ότι θα πρέπει να υπολογίσουμε την απόσταση από το σημείο προέλευσης στο σημείο (x, y), η οποία δίνεται από x 2 + y 2 Μπορείτε να υπολογίσετε την τετραγωνική ρίζα καλώντας την μέθοδο sqrt της τάξης Math με αυτό τον τρόπο: double distance = Math.sqrt(x * x + y * y); Σημειώστε ότι πρέπει να συμπεριλάβετε το όνομα της τάξης, μαζί με το όνομα της μεθόδου. Μέθοδοι όπως η Math.sqrt που ανήκουν σε μια τάξη ονομάζονται static methods.
7
Χρήσιμες μέθοδοι της τάξης Math Math.abs( x ) Επιστρέφει την απόλυτη τιμής του x Math.min( x, y ) Επιστρέφει το μικρότερο από τα x και y Math.max( x, y ) Επιστρέφει το μεγαλύτερο από τα x και y Math.sqrt( x ) Επιστρέφει η τετραγωνική ρίζα του x Math.log( x ) Επιστρέφει το φυσικό λογάριθμο του x (log e x ) Math.exp( x ) Επιστρέφει τον αντίστροφο λογάριθμο του x (e x ) Math.pow( x, y ) Επιστρέφει το x υψωμένο στη δύναμη y (x y ) Math.sin( theta ) Επιστρέφει το ημίτονο theta, σε ακτίνια Math.cos( theta ) Επιστρέφει το συνημίτονο του theta Math.tan( theta ) Επιστρέφει την εφαπτομένη του theta Math.asin( x ) Επιστρέφει τη γωνία της οποίας το ημίτονο είναι x Math.acos( x ) Επιστρέφει τη γωνία της οποίας το συνημίτονο είναι x Math.atan( x ) Επιστρέφει τη γωνία της οποίας η εφαπτομένη είναι x Math.toRadians( degrees ) Μετατρέπει μια γωνία από μοίρες σε ακτίνια Math.toDegrees( radians ) Μετατρέπει μια γωνία από ακτίνια σε μοίρες
8
Οι κλήσεις μεθόδων ως μηνύματα Στις αντικειμενοστρεφείς γλώσσες όπως η Java, η κλήση μιας μεθόδου συχνά περιγράφεται σαν αποστολή ενός μηνύματος σε ένα αντικείμενο. Για παράδειγμα, η κλήση της μεθόδου rect.setColor(Color.RED); Θεωρείται μεταφορικά ως αποστολή ενός μηνύματος στο αντικείμενο rect ζητώντας του να αλλάξει το χρώμα του. setColor(Color.RED) Το αντικείμενο που στέλνεται ένα μήνυμα καλείται δέκτης receiver. name ( arguments ); Το γενικό μοτίβο για την αποστολή ενός μηνύματος σε ένα αντικείμενο είναι
9
Γράφοντας τις δικές σας μεθόδους Η γενική μορφή του ορισμού μιας μεθόδου είναι scope type name ( argument list ) { statements in the method body } με το scope να υποδεικνύει ποιος έχει πρόσβαση στη μέθοδο, το type να είναι το είδος της τιμής που επιστρέφεται, το name είναι το όνομα της μεθόδου, και argument list είναι η λίστα δηλώσεων των μεταβλητών που χρησιμοποιούνται για να κρατήσουν τις τιμές του κάθε ορίσματος. Η πιο κοινή τιμή για το πεδίο εφαρμογής είναι private, που σημαίνει ότι η μέθοδος είναι διαθέσιμη μόνο εντός της δικής της τάξης. Εάν άλλες τάξεις πρέπει να έχουν πρόσβαση σε αυτή, το scope πρέπει να είναι public. Αν μια μέθοδος δεν επιστρέφει τιμή, το type πρέπει να είναι void. Τέτοιες μέθοδοι ονομάζονται και διαδικασίες.
10
Επιστρέφοντας τιμές από μια μέθοδο Μπορείτε να επιστρέψετε μια τιμή από μια μέθοδο γράφοντας return, η οποία συνήθως γράφεται ως return expression ; όπου expression είναι η Java έκφραση που καθορίζει την τιμή που θέλετε να επιστρέψετε. Ως παράδειγμα, ο ορισμός της μεθόδου private double feetToInches(double feet) { return 12 * feet; } μετατρέπει ένα όρισμα που αφορά μια απόσταση σε πόδια στην αντίστοιχη σε ίντσες, θεωρώντας ότι υπάρχουν 12 ίντσες σε ένα πόδι.
11
Μέθοδοι περιλαμβάνουσες εντολές ελέγχου Το σώμα μιας μεθόδου μπορεί να έχει εντολές κάθε τύπου, συμπεριλαμβανομένων εντολών ελέγχου. Για παράδειγμα, η ακόλουθη μέθοδος χρησιμοποιεί ένα if να βρει την μεγαλύτερη από δύο τιμές : private int max(int x, int y) { if (x > y) { return x; } else { return y; } Αυτό το παράδειγμα καθιστά σαφές, ότι οι εντολές επιστροφής μπορούν να χρησιμοποιηθούν σε οποιοδήποτε σημείο της μεθόδου και μπορούν να εμφανιστούν περισσότερες από μία φορές.
12
Η μέθοδος factorial Παραγοντικό (factorial) ενός αριθμου n ( συνήθως γράφεται ως n! ) ορίζεται ως το γινόμενο των ακέραιων από 1 εως n. Έτσι, το 5! είναι ίσο με 120, ως γινόμενο 1 x 2 x 3 x 4 x 5. private int factorial(int n) { int result = 1; for (int i = 1; i <= n; i++) { result *= i; } return result; } Ο ακόλουθος ορισμός χρησιμοποιεί ένα for loop για να υπολογιστεί μια παραγοντική συνάρτηση:
13
Μη-αριθμητικές μέθοδοι private String weekdayName(int day) { switch (day) { case 0: return "Sunday"; case 1: return "Monday"; case 2: return "Tuesday"; case 3: return "Wednesday"; case 4: return "Thursday"; case 5: return "Friday"; case 6: return "Saturday"; default: return "Illegal weekday"; } Οι μέθοδοι στην Java μπορούν να επιστρέφουν τιμές οποιουδήποτε τύπου. Η ακόλουθη μέθοδος, για παράδειγμα, επιστρέφει το αγγλικό όνομα της ημέρας της εβδομάδας, όταν δίνεται ένας αριθμός μεταξύ 0 (Sunday) και 6 (Saturday):
14
Μέθοδοι που επιστρέφουν γραφικά αντικείμενα Το βιβλίο περιλαμβάνει παραδείγματα μεθόδων που επιστρέφουν γραφικά αντικείμενα. Η ακόλουθη μέθοδος δημιουργεί ένα γεμάτο κύκλο με κέντρο στο σημείο (x, y), με ακτίνα r εικονοστοιχείων, που είναι γεμάτος με το καθορισμένο χρώμα: Αν δημιουργείτε ένα GraphicsProgram που απαιτεί πολλούς γεμάτους κύκλους σε διάφορα χρώματα, η μέθοδος createFilledCircle αποδεικνύεται ότι εξοικονομεί ένα σημαντικό μέρος κώδικα. private GOval createFilledCircle(double x, double y, double r, Color color) { GOval circle = new GOval(x - r, y - r, 2 * r, 2 * r); circle.setFilled(true); circle.setColor(color); return circle; }
15
Κατηγορηματικές Μέθοδοι Οι μέθοδοι που επιστρέφουν Boolean τιμές διαδραματίζουν σημαντικό ρόλο στον προγραμματισμό και ονομάζονται κατηγορηματικές Μέθοδοι (predicate methods) Η ακόλουθη μέθοδος επιστρέφει true αν το πρώτο όρισμα είναι διαιρετό από το δεύτερο, και false διαφορετικά: private boolean isDivisibleBy(int x, int y) { return x % y == 0; } Αφού έχετε ορίσει μια κατηγορηματική μέθοδο, μπορείτε να τη χρησιμοποιήσετε όπως οποιαδήποτε άλλη λογική τιμή. Π.χ. μπορείτε να εκτυπώσετε τους ακέραιους αριθμούς μεταξύ 1 και 100 που διαιρούνται με το 7 ως εξής: for (int i = 1; i <= 100; i++) { if (isDivisibleBy(i, 7)) { println(i); }
16
Χρησιμοποιώντας κατηγορηματικές μεθόδους αποτελεσματικά Οι νέοι προγραμματιστές συχνά αποφεύγουν τις Boolean τιμές και καταλήγουν με κακό κώδικα. Για παράδειγμα, ένας αρχάριος μπορεί να γράψει την isDivisibleBy έτσι: private boolean isDivisibleBy(int x, int y) { if (x % y == 0) { return true; } else { return false; } Ένα παρόμοιο πρόβλημα εμφανίζεται αν προσπαθείτε να ελέγξετε αν μια μέθοδος επιστρέφει true. Θα πρέπει να είστε προσεκτικοί για να αποφεύγετε τέτοιου είδους περιττές δοκιμές σε δικά σας προγράμματα. for (int i = 1; i <= 100; i++) { if (isDivisibleBy(i, 7) == true) { println(i); } Αν και αυτός ο κώδικας είναι τυπικά σωστός, είναι αρκετά άκομψος για να αξίζει το σύμβολο bug. private boolean isDivisibleBy(int x, int y) { if (x % y == 0) { return true; } else { return false; }
17
Άσκηση: έλεγχος δυνάμεων του δύο Γράψτε μια μέθοδο με όνομα isPowerOfTwo που παίρνει ένα ακέραιο n και επιστρέφει true αν το n είναι δύναμη του δύο, και false διαφορετικά. Οι δυνάμεις του 2 είναι 1, 2, 4, 8, 16, 32, … Αριθμοί που είναι μικρότεροι ή ίσοι με το μηδέν δεν μπορεί να είναι δυνάμεις του δύο. private boolean isPowerOfTwo(int n) { if (n < 1) return false; while (n > 1) { if (n % 2 == 1) return false; n /= 2; } return true; }
18
Η διαδικασία κλήσης των μεθόδων import acm.program.*; public class FactorialTable extends Program { public void run() { for (int i = LOWER; i<=UPPER; i++){ println(i + "! = " + factorial(i)); } private int factorial(int n) { int result = 1; for (int i = 1; i <= n; i++){ result *= i; } return result; } private static final int LOWER = 0; private static final int UPPER = 10; }
19
Η διαδικασία κλήσης των μεθόδων Κοιτώντας το προηγούμενο πρόγραμμα ολιστικά κάποιος θα μπορούσε να παρατηρήσει Ότι ο μετρητής i εμφανίζεται δύο φορές, μία στην μέθοδο run και μία στην μέθοδο factorial. Επίσης στην κλήση της factorial το όρισμα ονομάζεται i, ενώ στο ορισμό της μεθόδου ονομάζεται n. 1. Όλα αυτά θα μπορούσαν να προκαλέσουν σύγχυση, ωστόσο στην πράξη βοηθάνε το πρόγραμμα να είναι περισσότερο ξεκάθαρο και κατατετμημένο σε ανεξάρτητες ενότητες. Η ιδέα είναι ότι εντός της κάθε μεθόδου οι μεταβλητές είναι τοπικές, δηλ. αν και μπορούν να έχουν τα ίδια ονόματα με μεταβλητές άλλων μεθόδων είναι διαφορετικές μεταβλητές. 2.
20
Η διαδικασία κλήσης των μεθόδων Όταν καλείτε μια μέθοδο, θα συμβούν οι ακόλουθες ενέργειες: Η Java αξιολογεί τα ορίσματα στο πλαίσιο της μεθόδου κλήσης.1. Η Java στη συνέχεια αντιγράφει κάθε τιμή ορίσματος σε μια αντίστοιχη μεταβλητή, η οποία δημιουργείται σε μια νέα περιοχή μνήμης που ονομάζεται πλαίσιο στοίβας. Η ανάθεση ακολουθεί τη σειρά με την οποία εμφανίζονται τα ορίσματα: το πρώτο όρισμα αντιγράφεται στην πρώτη μεταβλητή κτλ. 2. Στη συνέχεια αξιολογούνται οι δηλώσεις στο σώμα της μεθόδου, χρησιμοποιώντας το νέο πλαίσιο στοίβας για τις τιμές των τοπικών μεταβλητών. 3. Όταν Java συναντά ένα return, υπολογίζει την τιμή επιστροφής και τα αντικαθιστά στην κλήση με αυτήν. 4. Στη συνέχεια απορρίπτει το πλαίσιο στοίβας για την μέθοδο και επιστρέφει στον καλούντα, συνεχίζοντας από εκεί που σταμάτησε. 5.
21
Μια συνάρτηση συνδυασμών Για να φανεί ο τρόπος κλήσεως των μεθόδων, παρουσιάζεται μια συνάρτηση C(n, k) που υπολογίζει τους συνδυασμούς, που είναι ο αριθμός των τρόπων που μπορεί κανείς να επιλέξει k στοιχεία από ένα σύνολο n αντικειμένων. Υποθέτουμε, ότι έχετε μια σειρά από πέντε νομίσματα: ένα σεντ, μια πεντάρα, μια δεκάρα, ένα τέταρτο, και ένα δολάριο: Πόσοι τρόποι υπάρχουν για να επιλέξετε δύο νομίσματα; σεντ + πεντάρα σεντ + δεκάρα σεντ + τέταρτο σεντ + δολάριο πεντάρα + δεκάρα πεντάρα + τέταρτο πεντάρα + δολάριο δεκάρα + τέταρτο δεκάρα + δολάριο τέταρτο + δολάριο για ένα σύνολο 10 τρόπων.
22
Συνδυασμοί και παραγοντικά Ευτυχώς, τα μαθηματικά παρέχουν έναν ευκολότερο τρόπο για να υπολογίσουμε τους συνδυασμούς αντί να μετράμε όλους τους τρόπους που δίδεται από τον τύπο: C(n, k) = n !n ! k !k !(n – k) !(n – k) ! x Έχοντας ήδη την μέθοδο factorial, Είναι εύκολο να μετατρέψετε αυτό τον τύπο σε μια μέθοδο Java, ως εξής: private int combinations(int n, int k) { return factorial(n) / (factorial(k) * factorial(n - k)); } Η επόμενη διαφάνεια προσομοιώνει τη λειτουργία των combinations και factorial στο πλαίσιο μιας απλής run.
23
Το πρόγραμμα Combinations Στο σημείο αυτό, το πρόγραμμα καλεί τη μέθοδο Combinations: 1. Αξιολόγηση των ορισμάτων n και k με τους ακέραιους αριθμούς 5 και 2. 2. Δημιουργία ενός νέου πλαισίου για τη μέθοδο Combinations. 3. Αρχικοποίηση των μεταβλητών n και k στις τιμές των ορισμάτων public void run() { int n = readInt("Enter number of objects in the set (n): "); int k = readInt("Enter number to be chosen (k): "); println("C(" + n + ", " + k + ") = " + combinations(n, k) ); } Combinations nk 10 Enter number of objects in the set (n): 5 C(5, 2) = 10 Enter number to be chosen (k): 25 2 private int combinations(int n, int k) { return factorial(n) / ( factorial(k) * factorial(n - k) ); } nk 25 12026 Το πρόγραμμα καλεί την factorial, εφαρμόζοντας την ίδια διαδικασία. Η μέθοδος factorial επιστρέφει την τιμή 120 στον καλούντα. Το πρόγραμμα καλεί ξανά την factorial, με όρισμα k. Αυτή η κλήση της factorial επιστρέφει 2. Το πρόγραμμα καλεί ξανά την factorial με όρισμα n - k. Η τελευταία κλήση της factorial επιστρέφει την τιμή 6. skip simulation private int factorial(int n) { int result = 1; for ( int i = 1 ; i <= n ; i++ ) { result *= i; } return result; } nresult 5 i 11226324412056 private int factorial(int n) { int result = 1; for ( int i = 1 ; i <= n ; i++ ) { result *= i; } return result; } nresult 2 i 11223 private int factorial(int n) { int result = 1; for ( int i = 1 ; i <= n ; i++ ) { result *= i; } return result; } nresult 3 i 1122634 public void run() { int n = readInt("Enter number of objects in the set (n): "); int k = readInt("Enter number to be chosen (k): "); println("C(" + n + ", " + k + ") = " + combinations(n, k) ); } nk 25
24
Αποσύνθεση Ένα από τα πιο σημαντικά πλεονεκτήματα των μεθόδων είναι ότι καθιστούν δυνατό το σπάσιμο ένος μεγάλου έργου σε απλούστερα κομμάτια. Αυτό ονομάζεται αποσύνθεση. Πλήρης Εργασία Υποθέστε ότι σας έχει δοθεί ένα μεγάλο έργο που σας φαίνεται πολύ μεγάλο για να είναι μια ενιαία μέθοδος run. Υποεργασία 1Υποεργασία 2Υποεργασία 3 Πριν ξεκινήσετε να γράφετε κώδικα, πρέπει να σκεφτείτε το πρόβλημα προσπαθώντας να σπάσετε την πλήρη εργασία σε απλούστερες υποεργασίες. Υποεργασία 2a Υποεργασία 2b Μερικές υποεργασίες μπορεί να είναι τόσο δύσκολες που να έχει νόημα να σπάσουν σε ακόμη μικρότερες υποεργασίες. Αυτό μπορεί συνεχίσει μέχρι κάθε υποεργασία να είναι διαχειρίσιμη. Ένα από τα πιο σημαντικά πλεονεκτήματα των μεθόδων είναι ότι καθιστούν δυνατό το σπάσιμο ενός μεγάλου έργου σε απλούστερα κομμάτια. Αυτό ονομάζεται αποσύνθεση. Μόλις έχετε ολοκληρώσει την αποσύνθεση, μπορείτε να γράψετε μια μέθοδο για την κάθε υποεργασία.
25
Επιλέγοντας μια στρατηγική αποσύνθεσης Μία από τις πιο λεπτές πτυχές του προγραμματισμού είναι η διαδικασία αποσύνθεσης μεγάλων εργασιών σε μικρότερες Συχνά η καλύτερη στρατηγική αποσύνθεσης για ένα πρόγραμμα ακολουθεί τη δομή του προβλήματος ότι το πρόγραμμα προορίζεται να επιλύσει στον πραγματικό κόσμο. Αν το πρόβλημα έχει φυσικές υποδιαιρέσεις, αυτές συνήθως παρέχουν μια καλή βάση για την αποσύνθεσή του. Κάθε υποεργασία στην αποσύνθεση θα πρέπει να εκτελεί μια λειτουργία που είναι εύκολο να ονομαστεί και να περιγραφεί. Ένας από τους πρωταρχικούς στόχους της αποσύνθεσης είναι να απλοποιήσει τη διαδικασία προγραμματισμού. Μια καλή στρατηγική αποσύνθεσης πρέπει να περιορίζει την εξάπλωση της πολυπλοκότητας. Γενικά, κάθε επίπεδο της αποσύνθεσης ασχολείται με ορισμένες λεπτομέρειες και αποφύγει να προωθεί αυτές σε υψηλότερα επίπεδα.
26
Σχεδιάζοντας ένα τρένο Ως παράδειγμα της αποσύνθεσης, χρησιμοποιούμε το πρόβλημα γραφής ενός προγράμματος GraphicsProgram που σχεδιάζει ένα τρένο : Αν και είναι δυνατό να γράψετε μία ενιαία run που να σχεδιάζει τα αναγκαία γραφικά αντικείμενα, ένα τέτοιο πρόγραμμα θα ήταν πολύ δύσκολο να διαβαστεί. Ευτυχώς, το πρόβλημα αποσυντίθεται φυσικά, τουλάχιστον στο πρώτο επίπεδο: public void run() { Draw the engine. Draw the boxcar. Draw the caboose. } DrawTrain
27
Χρησιμοποιώντας Ψευδοκώδικα Αν και η μέθοδος run public void run() { Draw the engine. Draw the boxcar. Draw the caboose. } υποδηλώνει την αποσύνθεση του προγράμματος DrawTrain, δεν είναι ακόμη σωστός κώδικας Java, αλλά ένας συνδυασμός Αγγλικών και Java, που συνοψίζει το περίγραμμα της λύσης που ονομάζεται ψευδοκώδικας Είναι σημαντικό να θυμάστε ότι δεν πρέπει να υλοποιήσετε κάθε ένα από τα βήματα για να μπορέσετε να μετατρέψετε αυτό τον ψευδοκώδικα σε Java. Κάθε μια από τις γραμμές στα αγγλικά είναι απλά μια κλήση μεθόδου. Αυτό που πρέπει να κάνετε σε αυτό το σημείο είναι να αποφασίσετε για κάθε μέθοδο ένα όνομα και ποια ορίσματα χρειάζεται.
28
Ορίσματα ή Σταθερές; Σε γραφικά προγράμματα όπως το παράδειγμα DrawTrain, υπάρχουν δύο στρατηγικές για την παροχή των επιμέρους μεθόδων και των πληροφοριών που χρειάζονται όπως τα μεγέθη και τις θέσεις των αντικειμένων: –Μπορείτε να χρησιμοποιήσετε σταθερές για τον καθορισμό των παραμέτρων. –Μπορείτε να περάσετε αυτές τις πληροφορίες ως ορίσματα της κάθε μεθόδου Κάθε στρατηγική έχει πλεονεκτήματα και μειονεκτήματα. Η χρήση σταθερών είναι εύκολη, αλλά σχετικά ανελαστική. Εάν έχετε ορίσει σταθερές για να καθορίσετε τη θέση του βαγονιού, μπορείτε να σχεδιάσετε μόνο ένα βαγόνι σε αυτή τη θέση. Η χρήση ορισμάτων είναι πιο περίπλοκη, αλλά κάνει πιο εύκολο να αλλάξετε αυτές τις τιμές. Πρέπει να βρείτε την κατάλληλη ισορροπία μεταξύ των δύο προσεγγίσεων με βάση αυτές τις κατευθυντήριες γραμμές: –Ορίσματα, όταν οι καλούντες θέλουν να παρέχουν διαφορετικές τιμές. –Σταθερές, όταν οι καλούντες είναι ικανοποιημένοι με μια τιμή.
29
Παράμετροι για την σχεδίαση βαγονιών τρένου Το πρόγραμμα DrawTrain προβαίνει στις ακόλουθες παραδοχές : –Ο καλών θα θέλει πάντα να παρέχει τη θέση του κάθε βαγονιού. –Όλα τα βαγόνια έχουν το ίδιο μέγεθος και την ίδια βασική δομή. –Οι μηχανές είναι πάντα μαύρες. –Τα βαγόνια έχουν πολλά χρώματα, με τον καλώντα να τα παράσχει. –Το βαγόνι των σιδηροδρομικών υπαλλήλων είναι πάντα κόκκινο. Οι παραδοχές αυτές υποδηλώνουν ότι οι κεφαλίδες για τις drawEngine, drawBoxcar, και drawCaboose θα είναι: private void drawEngine(double x, double y) private void drawBoxcar(double x, double y, Color color) private void drawCaboose(double x, double y)
30
Ψάχνοντας για κοινά χαρακτηριστικά Μια χρήσιμη στρατηγική στην αποσύνθεση είναι να ψάξουμε για κοινά χαρακτηριστικά ανάμεσα στα διαφορετικά μέρη του προγράμματος. Τέτοια κοινά χαρακτηριστικά μπορούν να υλοποιηθούν σε μια ενιαία μέθοδο. Στο DrawTrain, Κάθε βαγόνι έχει κοινή δομή που αποτελείται από το πλαίσιο τους τροχούς του, και ένα σύνδεσμο για να την σύνδεση με το διπλανό του. –Η μηχανή είναι μαύρη και έχει φουγάρο, καμπίνα και προφυλακτήρα. –Το βαγόνι είναι χρωματιστό και έχει πόρτες. –Το βαγόνι σιδηροδρομικών υπαλλήλων είναι κόκκινο και έχει τρούλο. Μπορείτε έτσι να γράψετε μια κοινή μέθοδο drawCarFrame για να σχεδιάσετε τα κοινά τμήματα των βαγονιών.
31
Αλγοριθμικές μέθοδοι Οι μέθοδοι είναι σημαντικές, επειδή παρέχουν μια δομή έκφρασης αλγορίθμων. Οι αλγόριθμοι είναι αφηρημένες εκφράσεις μιας λύσης. Η εφαρμογή ενός αλγορίθμου ως μεθόδου κάνει την αφηρημένη έκφραση, συγκεκριμένη. Οι αλγόριθμοι για την επίλυση ενός προβλήματος μπορεί να ποικίλουν στην απόδοση τους. Πρέπει να σκεφτείτε προσεκτικά όταν επιλέγετε έναν αλγόριθμο, επειδή μια κακή επιλογή μπορεί να είναι εξαιρετικά δαπανηρή. Η παράγραφος 5.5 του βιβλίου εξετάζει δύο αλγορίθμους για τον υπολογισμό του μέγιστου κοινού διαιρέτη των ακεραίων x και y, όπως ορίζεται ο μεγαλύτερος ακέραιος που διαιρεί πλήρως και τους δύο.
32
Προσεγγίσεις Brute-Force Μια στρατηγική για τον υπολογισμό του ΜΚΔ είναι να μετρήσουμε από τη μικρότερη τιμή προς τα πίσω μέχρι να βρούμε τον αριθμό που διαιρεί πλήρως και τους δύο: Αυτός ο αλγόριθμος πρέπει να τερματίζει για θετικές τιμές των x και y επειδή η τιμή της guess τελικά θα φτάσει το 1. Σε εκείνο το σημείο, η guess πρέπει να είναι ο ΜΚΔ, επειδή το while loop θα έχει ήδη δοκιμάσει όλα τα μεγαλύτερα. Ο έλεγχος κάθε δυνατότητας ονομάζεται brute-force. public int gcd(int x, int y) { int guess = Math.min(x, y); while (x % guess != 0 || y % guess != 0) { guess--; } return guess; }
33
Αλγόριθμος του Ευκλείδη Εάν χρησιμοποιείτε την brute-force προσέγγιση για τον υπολογισμό του ΜΚΔ για τα 1000005 και 1000000, το πρόγραμμα θα κάνει σχεδόν ένα εκατομμύριο βήματα για να βρει την απάντηση 5. public int gcd(int x, int y) { int r = x % y; while (r != 0) { x = y; y = r; r = x % y; } return y; } Μπορείτε να πάρετε απάντηση πολύ πιο γρήγορα αν χρησιμοποιείτε ένα καλύτερο αλγόριθμο. Ο Ευκλείδης περιέγραψε ένα πιο αποδοτικό τρόπο πριν από 23 αιώνες, που μοιάζει έτσι:
34
Πώς δουλεύει ο Αλγόριθμος του Ευκλείδη Αν χρησιμοποιείστε τον αλγόριθμο του Ευκλείδη στα 1000005 και 1000000, θα πάρετε τη σωστή απάντηση σε μόλις δύο βήματα, που είναι πολύ καλύτερα από τα εκατομμύρια βήματα που απαιτούνται από το brute force. Η μεγάλη διορατικότητα του Ευκλείδη ήταν ότι ο μέγιστος κοινός διαιρέτης των x και y θα πρέπει επίσης να είναι ο μέγιστος κοινός διαιρέτης του y και του υπόλοιπου του x διαιρούμενο με το y, και κατάφερε να αποδείξει την πρόταση αυτή στο Βιβλίο VII των Στοιχείων του. Είναι εύκολο να δείτε πώς λειτουργεί ο αλγόριθμος του Ευκλείδη, εάν σκέφτεστε το πρόβλημα γεωμετρικά, όπως έκανε ο Ευκλείδης. Η επόμενη διαφάνεια δείχνει τα βήματα όταν το x είναι 78 και το y είναι 33.
35
Παρουσίαση του αλγορίθμου 78 x 33 y Βήμα 1: Υπολογίζουμε το υπόλοιπο του 78 δια 33: 3312 x 33 y 12 Step 2: Υπολογίζουμε το υπόλοιπο του 33 δια 12: 912 x y Step 3: Υπολογίζουμε το υπόλοιπο του 12 δια 9: 12 9 3 x y Step 4: Υπολογίζουμε το υπόλοιπο του 9 δια 3: 9 3 33 Επειδή δεν υπάρχει υπόλοιπο, η απάντηση είναι 3:
36
Ασκήσεις μελέτης Ασκήσεις 1,2,3 και 4 του κεφαλαίου 5 από «Η Τέχνη και Επιστήμη της JAVA: Μια εισαγωγή στην Επιστήμη των Υπολογιστών», E. Roberts
37
Διάβασμα για το σπίτι Κεφάλαιο 5 από «Η Τέχνη και Επιστήμη της JAVA: Μια εισαγωγή στην Επιστήμη των Υπολογιστών», E. Roberts
Παρόμοιες παρουσιάσεις
© 2024 SlidePlayer.gr Inc.
All rights reserved.