Πρώτοι αριθμοί ΠΛΗΡΟΦΟΡΙΚΗ Ι JAVA Τμήμα θεωρίας με Α.Μ. σε 3, 7, 8 & 9 6/12/07 Ένας ακέραιος μεγαλύτερος του 1 είναι πρώτος αν έχει ακριβώς δύο διαιρέτες (τη μονάδα και τον εαυτό του). Πρόβλημα: έλεγχος αν κάποιος ακέραιος n είναι πρώτος ή όχι. Αλγόριθμος Α : - καταμέτρηση όλων των διαιρετών του n - αν οι διαιρέτες είναι 2 => ο n είναι πρώτος Όλοι οι πιθανοί διαιρέτες του n είναι n, άρα αρκεί να ελεγχθούν όλοι οι ακέραιοι στο διάστημα [1, n]. Πρόγραμμα για τον αλγόριθμο A : System.out.println( n? ); int n = input.nextint(); int numofdiv = 0; // plithos diairetwn for (int i=1; i<=n; i++) if (n%i == 0) numofdiv++; if (numofdiv == 2) System.out.println( Prime ); System.out.println( Not prime ); Βελτίωση της αποτελεσματικότητας του αλγόριθμου A και δημιουργία του αλγόριθμου B : Ο αλγόριθμος A έχει κάποια προβλήματα: - δεν είναι πρακτικός για μεγάλα n, διότι σε πολλές περιπτώσεις θα μπορούσε να έβγαζε συμπέρασμα ότι κάποιο n δεν είναι πρώτος αριθμός και παρόλα αυτά συνεχίζει τις επαναλήψεις μέχρι το τέλος του for. Π.χ., για n=81, από την 3 η κι 1
όλας επανάληψη όπου το 3 είναι διαιρέτης του 81, θα μπορούσε να εξαχθεί το συμπέρασμα ότι ο 81 δεν είναι πρώτος. Παρόλα αυτά, το πρόγραμμα θα συνεχίσει μέχρι την 81 η επανάληψη και μετά θα βγάλει το συμπέρασμα.. - αν ο n δεν διαιρείται με το 2, τότε δεν διαιρείται με κανέναν άρτιο, άρα περιττεύει η εξέταση πιθανών διαιρετών που είναι άρτιοι. - Αριθμοί μεγαλύτεροι της n δεν χρειάζεται να ελεγχθούν. Αν δ 1 δ 2 είναι δύο διαιρέτες του n: δ 1 x δ 2 = n, τότε ο ένας θα είναι οπωσδήποτε < n. Η «επίλυση» αυτών των προβλημάτων οδηγεί στον βελτιωμένο αλγόριθμο B. Πρόγραμμα για τον αλγόριθμο Β : System.out.println( n? ); int n = input.nextint(); boolean isprime = true; if ((n%2==0 && n>2) n==1) isprime = false; int divisor = 3; int limit = (int)math.sqrt(n) + 1; while (divisor<=limit && isprime) if (n%divisor == 0) isprime = false; divisor += 2; if (isprime) System.out.println( Prime ); System.out.println( Not prime ); 2
Ροή προγραμμάτων Με τον όρο «ροή προγράμματος» αναφερόμαστε στη σειρά με την οποία εκτελούνται οι εντολές ενός προγράμματος. Μέχρι τώρα έχουμε αναφερθεί στις ακόλουθες μορφές ροής: Σειριακή Επαναληπτική Υπό συνθήκη Μιά άλλη μορφή ροής ενός προγράμματος είναι αυτή που πραγματοποιείται μέσω της κλήσης μεθόδων: μέθοδος που μπορεί να βρίσκεται μέσα στην κλάση ή και μέσα σε κάποια άλλη κλάση. 3
Μέθοδοι Μέθοδος ονομάζεται ένα σύνολο συγκεντρωμένων εντολών με χαρακτηριστικό όνομα. (Είναι το αντίστοιχο των «συναρτήσεων» άλλων γλωσσών προγραμματισμού) Η φιλοσοφία των μεθόδων: - Εντοπισμός κάποιου υπο-προβλήματος που χρειάζεται να επιλυθεί σαν μέρος του προγράμματος - Αλγοριθμική επίλυση του υπο-προβλήματος και εγγραφή του αντίστοιχου κώδικα (μόνο μία φορά) - Ονομασία του κώδικα του υπο-προβλήματος μέθοδος - Χρήση της μεθόδου (κλήση, εκτέλεση ή τρέξιμο) (με το όνομά της) κάθε φορά που παρουσιάζεται το ίδιο υπο-πρόβλημα. Βασικά χαρακτηριστικά μεθόδων: - Επαναχρησιμοποιήσιμος κώδικας σε άλλα προγράμματα - Μη επανάληψη κώδικα στο ίδιο πρόγραμμα - «Μαύρα κουτιά» ενδιαφέρει το τί κάνουν, όχι το πώς το κάνουν - Βοηθούν στη λογική σχεδίαση του προγράμματος - Αποκρύπτουν προγραμματιστικές λεπτομέρειες Είδη μεθόδων: - Ορισμένες από τον προγραμματιστή - Βιβλιοθήκες (μέρος της Java), π.χ. println(), nextint(), sqrt() κτλ. Σχεδιασμός μεθόδων: - Κάθε μέθοδος καλείται από κάποια άλλη μέθοδο - Μπορεί να έχει δεδομένα εισόδου (τα παίρνει από τη μέθοδο που την καλεί) - Μπορεί να έχει δεδομένα εξόδου (τα επιστρέφει στη μέθοδο που την καλεί) - Έχει ένα όνομα (συνήθως μοναδικό, αλλά όχι πάντα «Πληροφορική ΙΙ») - Έχει ένα σύστημα ορισμού της επικοινωνίας της με το περιβάλλον Τα δύο τελευταία δηλώνονται με τον ορισμό της μεθόδου στην πρώτη της γραμμή στον κώδικα. 4
Ορισμός static μεθόδων: public static <τύπος> <όνομα>([παράμετροι]) Τί είναι το κάθε στοιχείο του ορισμού: public: ορατότητα η μέθοδος μπορεί να κληθεί και από μεθόδους άλλων κλάσεων, όχι μόνο της κλάσης μέσα στην οποία υπάρχει. (Περισσότερα σε επόμενο μάθημα) static: είδος η μέθοδος έχει ένα «αντίγραφο» για όλα τα αντικείμενα της κλάσης στην οποία βρίσκεται και όχι ένα αντίγραφο για κάθε αντικείμενο. (Περισσότερα σε επόμενο μάθημα) τύπος: - void εάν δεν επιστρέφει τίποτα - πρωτογενής τύπος (int, double, boolean, char, κτλ.) ανάλογα με τον τύπο της μεταβλητής που επιστρέφει - String εάν επιστρέφει κάποιο string παράμετροι: μεταβλητές εισόδου, οι οποίες έχουν συγκεκριμένες τιμές στη μέθοδο κλήσης της μεθόδου και χρησιμοποιούνται με αυτές τις τιμές μέσα στη μέθοδο. (Αν δεν υπάρχουν παράμετροι εισόδου, οι παρενθέσεις απλά μένουν κενές) Η εντολή return: i) Χρησιμοποιείται στις μεθόδους συγκεκριμένουν τύπου (δηλ. όχι void) για να επιστρέψει την τιμή της μεταβλητής εξόδου return μεταβλητή; π.χ. public static int method1(int x) int y = 2*x; return y; ii) Χρησιμοποιείται στις void μεθόδους σαν εντολή εξόδου από τη μέθοδο (και επιστροφής της ροής του κώδικα στην αρχική μέθοδο κλήσης). 5
Η χρήση αυτή είναι σπάνια, συνήθως χρησιμοποιείται υπό συνθήκη και καλό είναι να αποφεύγεται (υπάρχουν καλύτεροι τρόποι που επιτυγχάνουν ανάλογο αποτέλεσμα «Πληροφορική ΙΙ»). π.χ. public static void method2() boolean error; if (error) return; Άρα, ένα πρόγραμμα μπορεί να έχει πολλές κλάσεις και κάθε κλάση μπορεί να έχει πολλές μεθόδους. Η μέθοδος main είναι πάντα μία σε ένα πρόγραμμα. Η κλάση που την περιέχει λέγεται κλάση εφαρμογής. Οι υπόλοιπες κλάσεις λέγονται κλάσεις υποστήριξης. Δηλαδή, ένα πρόγραμμα μπορεί να έχει την ακόλουθη δομή: ClassA main method1 ClassB method2 method3 ClassC method4 method5 method6 ClassD method7 Κλάση εφαρμογής: ClassA Κλάσεις υποστήριξης: ClassB, ClassC, ClassD 6
Παράδειγμα με κλήση μεθόδου στην ίδια κλάση: import java.util.*; public class Circle //methodos pou ypologizei epifaneia kyklou: public static double circlearea(double r) return Math.PI*r*r; // methodos pou ypologizei epifaneia daktyliou: public static double ringarea(double rin, double rout) double innerarea = circlearea(rin); double outterarea = circlearea(rout); return (outterarea innerarea); // H methodos main: public static void main(string [] args) Scanner input = new Scanner(System.in); System.out.println( Radius 1? ); double r1 = input.nextdouble(); System.out.println( Radius 2? ); double r2 = input.nextdouble(); double area = (r1 < r2)? ringarea(r1,r2) : ringarea(r2,r1); System.out.println( The area of the ring is: + area); 7