Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών...

135
Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών, Προγραμματισμός Η/Υ, θεωρία, Α Τμήμα (01AB) Ειδικότητες μηχανικού και πώς προέκυψαν από τους πολ. Μηχανικούς. Αντικείμενο πολιτικού μηχανικού που διεκδικούν άλλες ειδικότητες μηχανικού. Hollerith: ηλεκτρομηχανικά συστήματα με διάτρητες καρτέλες, μεταφορικούς ιμάντες και ηλεκτρικές πόρτες. Εισαγωγή στην ηλεκτρονική, πύλες AND, OR, NOT – πίνακες αληθείας. Δεκαδικό σύστημα. Δυαδικό σύστημα, άλγεβρα Boole, αναπαράσταση ακεραίων σε δυαδικό σύστημα. Πρόσθεση, πολλαπλασιασμός, διαίρεση με άπειρα “δεκαδικά”. Μονοψήφια δυαδική πρόσθεση με κρατούμενο. Ημιαθροιστής. Συνδυασμός 2 ημιαθροιστών σε αθροιστή. Παράλληλοι αθροιστές: 32->32bit, 64->64bit. Εισαγωγή αριθμών με καλώδια. Επιλογή είδους πράξης με καλώδια. Πύλες AND, OR που επιλέγουν αθροιστή ή πολλαπλασιαστή ανάλογα με 1 bit. Πύλες που επιλέγουν πρόσθεση, αφαίρεση, διαίρεση με 2 bits. Καταχωρητής. Μνήμη (flip-flop). Εισαγωγή επιλογής με διάτρητη κάρτα (πρόγραμμα) και αριθμών (δεδομένα) που λαμβάνουν μέρος στις πράξεις -> Γλώσσα μηχανής. Assembly. Fortran. Άλλες γλώσσες προγραμματισμού. Πλεονεκτήματα/μειονεκτήματα Fortran. bits: μονάδα μνήμης που αποθηκεύει ένα δυαδικό ψηφίο, Byte=8bits επινοήθηκε από τους 8bitους επεξεργαστές. Η μονάδα word=16bits για 16bitους υπολογιστές δεν έτυχε ευρείας αποδοχής. Μετράμε τη μνήμη σε Kbytes ή KB=1000Bytes, MB=10 6 Bytes, GB=10 9 Bytes. Προσοχή: Kb=Kbits=1000bits, Mb=10 6 bits, Gb=10 9 bits. Επίσης: KiB=2 10 bytes = 1024 bytes, MiB= 2 20 bytes= 1048576 Bytes ≈ 1.05MB, GiB= 2 30 bytes= 1073741824 Bytes ≈ 1.07GB (διαβάζονται Kibi, Mibi, Gibi Bytes ή κίμπι, μίμπι, γκίμπι μπαιτς). Διαφορά στην αναπαράσταση μεταξύ ακεραίων και πραγματικών αριθμών. Σημαντικά ψηφία. Αναπαράσταση σε “κανονική” μορφή, δηλαδή πραγματικός αριθμός < 1 πολλαπλασιασμένο με μία δύναμη του 10, με το πρώτο δεκαδικό στοιχείο μη μηδενικό. Αποθηκεύεται μόνο ο πραγματικός αριθμός (τα σημαντικά ψηφία) και η δύναμη. Αυτή την αναπαράσταση χρησιμοπιεί ο υπολογιστής αλλά με δυαδικούς αριθμούς αντί για δεκαδικούς. Και επειδή το 0.4 δεν έχει ακριβή αναπαράσταση στο δυαδικό σύστημα (άπειρα και επαναλαμβανόμενα ψηφία μετά την υποδιαστολή), αναγκαστικά γίνεται αποκοπή μετά από κάποια (πχ 26). Αποτέλεσμα ότι 4 <> 4.0 Ακέραιες σταθερές 1, 0, +123, -15. Μπορούμε να βάλουμε κάτω παύλα με ένα νούμερο (2, 4, 8): +123_4. Αυτό σημαίνει ότι ο αριθμός απαιτεί 4 Bytes μνήμη ή 32 δυαδικά ψηφία που αντιστοιχούν περίπου από -2 δισεκατομμύρια έως 2 δισεκατομμύρια. Οι ακέραιοι με 4 Bytes, που είναι και default ακέραιοι (δηλαδή αν δεν βάλουμε κάτω παύλα) είναι αρκετοί για το 99.9% όλων των θεμάτων του πολ. Μηχανικού. Ομοίως οι πραγματικοί: 3.14, -2.718, +33.33. Επίσης 3.14E-8, 12.3E4, ή 12.34E+4. Για πραγματικούς 4 Bytes (default): 3.14E1_4 Για πραγματικούς 8 bytes (διπλής ακριβείας): 3.14Ε1_8. Η πραγματικοί με 8 Bytes (διπλής ακριβείας είναι αρκετοί για το 99.9% των θεμάτων του πολ. Μηχανικου. Για λόγους απλότητας θα χρησιμοποιούμε εν γένει πραγματικούς 4 bytes που αρκούν για σημαντικό ποσοστό των θεμάτων πολ. Μηχανικού, αλλά όχι για όλα τα θέματα (πχ δυναμική ανάλυση κατασκευών, μηκοτομές μεγάλων οδών). Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 1

Transcript of Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών...

Page 1: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών, Προγραμματισμός Η/Υ, θεωρία, Α Τμήμα (01AB) Ειδικότητες μηχανικού και πώς προέκυψαν από τους πολ. Μηχανικούς. Αντικείμενο πολιτικούμηχανικού που διεκδικούν άλλες ειδικότητες μηχανικού.Hollerith: ηλεκτρομηχανικά συστήματα με διάτρητες καρτέλες, μεταφορικούς ιμάντες καιηλεκτρικές πόρτες. Εισαγωγή στην ηλεκτρονική, πύλες AND, OR, NOT – πίνακες αληθείας.Δεκαδικό σύστημα. Δυαδικό σύστημα, άλγεβρα Boole, αναπαράσταση ακεραίων σε δυαδικόσύστημα. Πρόσθεση, πολλαπλασιασμός, διαίρεση με άπειρα “δεκαδικά”. Μονοψήφια δυαδικήπρόσθεση με κρατούμενο. Ημιαθροιστής. Συνδυασμός 2 ημιαθροιστών σε αθροιστή. Παράλληλοιαθροιστές: 32->32bit, 64->64bit. Εισαγωγή αριθμών με καλώδια. Επιλογή είδους πράξης μεκαλώδια. Πύλες AND, OR που επιλέγουν αθροιστή ή πολλαπλασιαστή ανάλογα με 1 bit. Πύλεςπου επιλέγουν πρόσθεση, αφαίρεση, διαίρεση με 2 bits. Καταχωρητής. Μνήμη (flip-flop).Εισαγωγή επιλογής με διάτρητη κάρτα (πρόγραμμα) και αριθμών (δεδομένα) που λαμβάνουν μέροςστις πράξεις -> Γλώσσα μηχανής. Assembly. Fortran. Άλλες γλώσσες προγραμματισμού. Πλεονεκτήματα/μειονεκτήματα Fortran.

bits: μονάδα μνήμης που αποθηκεύει ένα δυαδικό ψηφίο, Byte=8bits επινοήθηκε από τους 8bitουςεπεξεργαστές. Η μονάδα word=16bits για 16bitους υπολογιστές δεν έτυχε ευρείας αποδοχής.Μετράμε τη μνήμη σε Kbytes ή KB=1000Bytes, MB=106 Bytes, GB=109 Bytes. Προσοχή:Kb=Kbits=1000bits, Mb=106 bits, Gb=109 bits. Επίσης: KiB=210 bytes = 1024 bytes, MiB= 220

bytes= 1048576 Bytes ≈ 1.05MB, GiB= 230 bytes= 1073741824 Bytes ≈ 1.07GB (διαβάζονταιKibi, Mibi, Gibi Bytes ή κίμπι, μίμπι, γκίμπι μπαιτς).

Διαφορά στην αναπαράσταση μεταξύ ακεραίων και πραγματικών αριθμών. Σημαντικά ψηφία.Αναπαράσταση σε “κανονική” μορφή, δηλαδή πραγματικός αριθμός < 1 πολλαπλασιασμένο με μίαδύναμη του 10, με το πρώτο δεκαδικό στοιχείο μη μηδενικό. Αποθηκεύεται μόνο ο πραγματικόςαριθμός (τα σημαντικά ψηφία) και η δύναμη. Αυτή την αναπαράσταση χρησιμοπιεί ο υπολογιστήςαλλά με δυαδικούς αριθμούς αντί για δεκαδικούς. Και επειδή το 0.4 δεν έχει ακριβή αναπαράστασηστο δυαδικό σύστημα (άπειρα και επαναλαμβανόμενα ψηφία μετά την υποδιαστολή), αναγκαστικάγίνεται αποκοπή μετά από κάποια (πχ 26). Αποτέλεσμα ότι 4 <> 4.0

Ακέραιες σταθερές 1, 0, +123, -15. Μπορούμε να βάλουμε κάτω παύλα με ένα νούμερο (2, 4, 8):+123_4. Αυτό σημαίνει ότι ο αριθμός απαιτεί 4 Bytes μνήμη ή 32 δυαδικά ψηφία που αντιστοιχούνπερίπου από -2 δισεκατομμύρια έως 2 δισεκατομμύρια. Οι ακέραιοι με 4 Bytes, που είναι καιdefault ακέραιοι (δηλαδή αν δεν βάλουμε κάτω παύλα) είναι αρκετοί για το 99.9% όλων τωνθεμάτων του πολ. Μηχανικού.Ομοίως οι πραγματικοί: 3.14, -2.718, +33.33. Επίσης 3.14E-8, 12.3E4, ή 12.34E+4. Γιαπραγματικούς 4 Bytes (default): 3.14E1_4Για πραγματικούς 8 bytes (διπλής ακριβείας): 3.14Ε1_8. Η πραγματικοί με 8 Bytes (διπλήςακριβείας είναι αρκετοί για το 99.9% των θεμάτων του πολ. Μηχανικου.Για λόγους απλότητας θα χρησιμοποιούμε εν γένει πραγματικούς 4 bytes που αρκούν γιασημαντικό ποσοστό των θεμάτων πολ. Μηχανικού, αλλά όχι για όλα τα θέματα (πχ δυναμικήανάλυση κατασκευών, μηκοτομές μεγάλων οδών).

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 1

Page 2: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Δευτέρα 14/4/2014 10:45-14:30, B' πολ. Μηχανικών, Προγραμματισμός Η/Υ, θεωρία, Α Τμήμα (01AB) Δεν επιτρέπεται η μίξη πραγματικών και ακεραίων στην ίδια παράσταση για ακαδημαϊκούς λόγους.Αριθμοί (και άλλες σταθερές) στη Fortran. Ακέραιοι, πραγματικοί, μιγαδικοί, πραγματικοί διπλήςακριβείας, μιγαδικοί διπλής ακριβείας, κείμενο, και αναφορά στις λογικές μεταβλητές.Πλεονεκτήματα διπλής ακριβείας: καλύτερη ακρίβεια. Μειονεκτήματα: μνήμη και χρόνοςυπολογισμών.Σταθερές στη Fortran: Ακέραιοι, πραγματικοί, μιγαδικοί, πραγματικοί διπλής ακριβείας, μιγαδικοίδιπλής ακριβείας, κείμενο, λογικές. Πράξεις μεταξύ ακεραίων. Για περισσότερους από 2 αριθμούςοι πράξεις γίνονται από αριστερά προς τα δεξιά, εκτός από τις δυνάμεις που γίνονται από δεξιάπρος τα αριστερά.

Πράξεις μεταξύ πραγματικών σταθερών. Δεν πρέπει να γίνεται μίξη απλής και διπλής ακρίβειας.Για περισσότερους από 2 αριθμούς οι πράξεις γίνονται από αριστερά προς τα δεξιά, εκτός από τιςδυνάμεις που γίνονται από δεξιά προς τα αριστερά.Ακέραια διαίρεση. Προσοχή διότι είναι συνηθισμένο λάθος.

Προτεραιότητα πράξεων.1. Παρενθέσεις.2. Δυνάμεις. Δεξιά προς τα αριστερά, όπως στα μαθηματικά A**K**M = A**(K**M)

akm

=a(km)

3. Πολλαπλασιασμοί και διαιρέσεις. Από τα αριστερά προς τα δεξιά.4. Προσθέσεις και αφαιρέσεις. Από τα αριστερά προς τα δεξιά.

Ασκήσεις για εμπέδωση. Μοναδική εξαίρεση στη μικτή αριθμητική: ύψωση οποιουδήποτε αριθμού(ακέραιου, πραγματικού, μιγαδικού, διπλής ακριβείας, διπλής ακριβείας μιγαδικού) σε ακέραιαδύναμη:

2 ** 3, 2.5 **3, 3.1E2 ** 4, 5.0_8 ** 5, (3.12, 2.714) ** 2, (3.12_8, 2.714_8) ** 2Προσοχή: 5.0 ** (-2) = 0.04, αλλά 5**(-2) = 0 (ακέραια διαίρεση: 1/5**2 = 1/25 = 0!)

Διευκρίνηση ακέραιου και πραγματικού εκθέτη στις δυνάμεις.1. Ακέραιος εκθέτης. Ο μεταγλωττιστής υπολογίζει μία ακέραια δύναμη ως πολλαπλό

πολλαπλασιασμό. Δηλαδή η παράσταση 3.14**4 υπολογίζεται ως 3.14*3.14*3.14*3.14 (ομεταγλωττιστής μπορεί να κάνει εξοικονόμηση θέτοντας T=3.14*3.14 και μετάυπολογίζοντας T*T).

2. Πραγματικός εκθέτης. Στα μαθηματικά ο υπολογισμός δυνάμεων με ρητούς εκθέτες γίνεται

ως a(

mn)

=n√xm . Για πραγματικούς εκθέτες γ δύναμη ορίζεται ως ab=exp(b⋅loga) όπου

exp(x )=ex . Αυτός ο τύπος είναι γενικός και χρησιμοποιείται από το μεταγλωττιστή γιαπραγματικούς εκθέτες.

3. Συνέπεια είναι ότι η δύναμη 3.14**4 που καταλήγει σε 4 (ή 2) πολλαπλασιασμούςυπολογίζεται πιο γρήγορα από τη 3.14**4.0 που καταλήγει στον υπολογισμό τωνσυναρτήσεων log(x) και exp(x) (που υπολογίζονται με ανάπτυγμα σε σειρά Taylor). Επίσηςη ύψωση σε ακέραια δύναμη εν γένει δίνει πιο ακριβή αποτελέσματα, και ειδικά σεακεραίους αριθμούς δίνει το ακριβές αποτέλεσμα.

4. Συνέπεια των παραπάνω είναι ότι (-3.14)**4.0 καταλήγει σε σφάλμα εκτέλεσης τουπρογράμματος (runtime error) αφού ο λογάριθμος αρνητικού αριθμού δεν υπάρχει.

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 2

Page 3: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

ΜεταβλητέςΜέχρι τώρα είπαμε για σταθερές. Μεταβλητή στη Fortran95 (και άνω) είναι μία θέση μνήμηςυπολογιστή που μπορεί να αποθηκεύσει έναν αριθμό ή ένα κείμενο. Κάθε μεταβλητή ονοματίζεταιμε όνομα που αρχίζει από λατινικό γράμμα, έχει μήκος 31 χαρακτήρες (χαρακτήρας είναι έναγράμμα, ένα ψηφίο, μία τελεία, ένα κόμα, ένα κενό, μία παρένθεση, ένα σύμβολο πράξης ή έναειδικό σύμβολο !#& κλπ) και οι υπόλοιποι 30 χαρακτήρες είναι λατινικά γράμματα, ψηφία ή ηκάτω παύλα. Προσοχή είναι λάθος να χρησιμοποιηθούν ελληνικά γράμματα για ονομασίαμεταβλητή.Στη FORTRAN77 οι μεταβλητές μπορεί να είναι μέχρι 6 χαρακτήρες.Εξορισμού ο κανόνας είναι οι μεταβλητές που αρχίζουν από I,J,K,L,M,N είναι ακέραιες και όλες οιυπόλοιπες πραγματικές.

Παραδείγματα βιβλίου.

Μπορούμε να αλλάξουμε τον τύπο μια μεταβλητής:

INTEGER(4) :: P, BAREAL :: I, JCOMPLEX(8) :: Z, ZADOUBLE PRECISION :: DF, X ή REAL(8) :: DF, XDOUBLE COMPLEX :: ZC ή COMPLEX(16) :: ZCCHARACTER(LEN=12) :: AA

Παρόλο που μπορεί να αλλάξει ο τύπος μεταβλητές, προτείνεται να μην παραβαίνεται ο κανόνας,γιατί ακολουθείται για περισσότερα από 50 χρόνια. Μη τήρηση του κανόνα μπορεί εύκολα ναοδηγήσει σε παρανοήσεις του κώδικα όταν διαβάζεται από άλλους.Δεν υπάρχει κανόνας για μεταβλητές μιγαδικών, κειμένου και διπλής ακριβείας. Συνηθίζεται όμως(όχι ευρέως) οι μεταβλητές κειμένου να αρχίζουν από A, οι μιγαδικές από C ή Z (και απλής καιδιπλής ακριβείας) και οι πραγματικές διπλής ακριβείας από D (αν όλες οι πραγματικές μεταβλητέςσε ένα πρόγραμμα είναι διπλής ακριβείας τότε συνηθίζεται ευρέως να ακολουθείται ο κανόνας γιατις πραγματικές μεταβλητές απλής ακριβείας δηλαδή αν αρχίζουν από A-H ή από O-Z).

Έτοιμες συναρτήσειςΗ Fortran δίνει πολλές έτοιμες συναρτήσεις. Τα ονόματα των συναρτήσεων έχουν το ίδιο κανόναμε τις μεταβλητές. Το πρώτο γράμμα δηλώνει αν το αποτέλεσμα της συνάρτησης θα είναιπραγματικός ή ακέραιος αριθμός. Έτσι αν είναι από I έως N η συνάρτηση “επιστρέφει” ακέραιοαριθμό (δηλαδή το αποτέλεσμά της είναι ακέραιος αριθμός), αλλιώς επιστρέφει πραγματικόαριθμό. Η συνάρτηση εφαρμόζεται σε έναν αριθμό (που καλείται “'όρισμα” της συνάρτησης ήενεργή παράμετρος) ο οποίος μπορεί να είναι ακέραιος ή πραγματικός αλλά όχι και τα δύο. Μπορείεπίσης να εφαρμοστεί σε μία μεταβλητή, ή μία αριθμητική παράσταση.Συνάρτηση FORTRAN Επιστρέφει Παράμετρος

sinx SIN(X) πραγματικό πραγματικό

cosx COS(X) πραγματικό πραγματικό

tanx TAN(X) πραγματικό πραγματικό

tan-1x ATAN(X) πραγματικό πραγματικό

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 3

Page 4: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

√ x SQRT(X) πραγματικό πραγματικό

ex EXP(X) πραγματικό πραγματικό

logex ALOG(X) πραγματικό πραγματικό

log10x ALOG10(X) πραγματικό πραγματικό

Μετατροπή πραγματικού σε ακέραιο με αποκοπήδεκαδικών

INT(X, KIND) πραγματικό ακέραιο

Μετατροπή ακεραίου σε πραγματικό REAL(I, KIND) ακέραιο πραγματικό

|x| ABS(X) πραγματικό πραγματικό

{i} IABS(I) ακέραιο ακέραιο

i modulo j MOD(I, J) ακέραιο ακέραια

Αριστερόστροφη γωνία διευθύνσεως από τοάξονα x: tan-1(dy/dx)

ATAN2(DY, DX) πραγματικό πραγματικά

Οι τριγωνομετρικές συναρτήσεις δέχονται ή επιστρέφουν γωνίες υποχρεωτικά σε rad. ΣτηFortran95 oι συναρτήσεις SIN(X), COS(X), TAN(X), ATAN(X), SQRT(X), EXP(X), ALOG(X),ABS(X), MOD(I, J), ATAN2(DY, DX) είναι generic (γενικού τύπου), δηλαδή επιστρέφουν είδοςκαι τύπο μεταβλητές ό,τι είναι και το X (ή τα DX,DY ή τα I,J).

Μικτή αριθμητικήΣτη FORTRAN77 δεν επιτρέπονται οι πράξεις μεταξύ ακεραίων και πραγματικών αριθμών επειδήέχουν τελείως διαφορετική αναπαράσταση. Μετατροπή μεταξύ ακεραίων γίνονται με ανάθεση:A=3.14K = A Τα δεκαδικά στοιχεία της A αποκόπτονται. Η μεταβλητή K περιέχει τον αριθμό 3A=5.999999K = A Τα δεκαδικά στοιχεία της A αποκόπτονται. Η μεταβλητή K περιέχει τον αριθμό 5

K = 3Α = Κ Συμπληρώνονται μηδενικά ως δεκαδικά. Η μεταβλητή K περιέχει τον αριθμό 3.0

Εναλλακτικά μπορούν να χρησιμοποιηθούν οι συναρτήσεις μετατροπής:

A = 3.14 + K ΛΑΘΟΣ: μικτή

B = K ΣΩΣΤΟ: ΠΕΡΙΦΡΑΣΤΙΚΗ ΜΕΤΑΤΡΟΠΗA = 3.14 + B

A = 3.14 + FLOAT(K) ΣΩΣΤΟ: ΑΜΕΣΗ ΜΕΤΑΤΡΟΠΗ: FORTRAN77A = 3.14 + REAL(K) ΣΩΣΤΟ: ΑΜΕΣΗ ΜΕΤΑΤΡΟΠΗ: Προτεινόμενο για Fortran95

I = 99 + A ΛΑΘΟΣ: μικτή

K = A ΣΩΣΤΟ: ΠΕΡΙΦΡΑΣΤΙΚΗ ΜΕΤΑΤΡΟΠΗI = 99 + K

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 4

Page 5: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

I = 99 + INT(A) ΣΩΣΤΟ: ΑΜΕΣΗ ΜΕΤΑΤΡΟΠΗ

Προσοχή στο λάθος:A = 3.14 + FLOAT(B) ΛΑΘΟΣ: Η συνάρτηση FLOAT() δέχεται μόνο ακέραιο όρισμαI = 99 + INT(K) ΛΑΘΟΣ: Η συνάρτηση INT() δέχεται μόνο πραγματικό όρισμα

Για τις Fortran95 και μετά, γίνεται αυτόματα μετατροπή όπου χρειάζεται. Για ακαδημαϊκούςλόγους, θα θεωρείται λανθασμένη η μικτή αριθμητική ακόμα και σε Fortran95 και μετά.

Άσκηση Πυθαγόρειο Θεώρημα 1Να υπολογιστεί η υποτείνουσα τριγώνου για πλευρές α=5 και β=7.Πρέπει να χρησιμοποιηθούν πραγματικοί αριθμοί.

PROGRAM PYTHAGA = 5.0B = 7.0C = SQRT(A**2 + B**2)END PROGRAM PYTHAG

Οι εντολές PROGRAM, END είναι μη εκτελέσιμες εντολές και χρησιμεύουν για να δείξουν τηναρχή και το τέλος του προγράμματος στο μεταγλωττιστή. Μπορούν να γραφούν μόνο μία φορά γιακάθε πρόγραμμα (ή υποπρόγραμμα). Η εντολή STOP σταματάει το πρόγραμμα και επιστρέφει τονέλεγχο στο λειτουργικό σύστημα (πχ LINUX, WINDOWS) και είναι απαραίτητη στηFORTRAN77. Η Fortran95 εισάγει από μόνη της το STOP πριν από το END, και έτσι το STOPείναι προαιρετικό.

Παρακάτω θα χρησιμοποιήσουμε πραγματικούς 4 bytes για ευκολία.

Άσκηση Πυθαγόρειο Θεώρημα 2Για να μπορεί ο χρήστης να δει το αποτέλεσμα (και τα δεδομένα) στην οθόνη.

PROGRAM PYTHAGA = 5.0B = 7.0WRITE (*, *) A, BC = SQRT(A**2 + B**2)WRITE (*, *) CEND PROGRAM PYTHAG

Μία σειρά στην οθόνη ανά WRITE.

Άσκηση Πυθαγόρειο Θεώρημα 3Για να μπορεί ο χρήστης να δει τι είναι τα νούμερα που γράφονται στην οθόνη

PROGRAM PYTHAGA = 5.0B = 7.0WRITE (*, *) 'A:', A, 'B:', BC = SQRT(A**2 + B**2)

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 5

Page 6: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

WRITE (*, *) 'Υποτείνουσα:', CEND PROGRAM PYTHAG

Άσκηση Πυθαγόρειο Θεώρημα 4 Για να μπορεί ο χρήστης να δώσει διαφορετικά κάθε φορά δεδομένα

PROGRAM PYTHAGWRITE (*, *) 'Δώστε A και B'READ (*, *) A, BWRITE (*, *) 'A:', A, 'B:', BC = SQRT(A**2 + B**2)WRITE (*, *) 'Υποτείνουσα:', CEND PROGRAM PYTHAG

Υπάρχουν δύο μόνο τρόποι για να δώσετε τιμή σε μία μεταβλητή. Ο πρώτος είναι με ανάθεση:A = 3.14

Ο δεύτερος είναι με ανάγνωση από πληκτρολόγιο ή οθόνη:READ (*, *) A

Με την εντολή READ εμφανίζεται ένα μαύρο παράθυρο και ο υπολογιστής περιμένει ναπληκτρολογήσετε έναν (εδώ πραγματικό) αριθμό και να πατήσετε enter. Ο αριθμός αυτός μπαίνειστη μεταβλητή.Αν δεν δοθεί τιμή σε μία μεταβλητή (με έναν από τους 2 τρόπους) η μεταβλητή περιέχει αυθαίρετοαριθμό που τυχαίνει να είναι στη μνήμη του υπολογιστή (από προηγούμενο πρόγραμμα ή από τολειτουργικό σύστημα). Κάθε φορά που θα τρέχει το πρόγραμμα αυτός ο αριθμός θα είναιδιαφορετικός και σίγουρα ΔΕΝ θα είναι μηδέν. Συνεπώς σε κάθε μεταβλητή που χρησιμοποιείταιστο πρόγραμμα πρέπει να δίνεται μία τιμή, ΠΡΙΝ χρησιμοποιηθεί σε κάποιο υπολογισμό.

Άσκηση Υπολογισμός οπλισμούΔεδομένα b, h, Μ

PROGRAM ANTOXWRITE (*, *) 'Δώστε διαστάσεις διατομής b και h'READ (*, *) B, HWRITE (*, *) 'Δώστε μέγιστη ροπή'READ (*, *) AMC = 20.0S = 500.0FCD = C *1000.0 / 1.5FYD = S *1000.0 / 1.15D = H – 0.03AM = AM / (B * D**2 * FCD)W = 0.84 * (1.0 – SQRT(1.0 – 2.4*AM))AS1 = B * D * FCD / FYD * WWRITE (*, *) 'Οπλισμός:', AS1END PROGRAM ANTOX

Άσκηση: Υπολογισμός ΠαροχήςΔεδομένα πλάτος ροής b, και βαθος ροής h. Η κλίση s=0.5% και ο συντελεστής manning n=0.015είναι σταθερές. V=1/n R ^ (2/3) s ^ (1/2), R=bh/(b+2h), Q=bhV

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 6

Page 7: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

PROGRAM AGOGWRITE (*, *) 'Δώστε διαστάσεις διατομής b και h'READ (*, *) B, HS = 0.5 !Λογικό λάθος: 0.5%N = 0.015 !Λάθος: πρέπει πραγματική μεταβλητήV = 1/N*R**2/3*SQRT(S) !ακερ.διαρ., λείπουν παρενθέσειςR=B*H/(B+2*H) !μικτή, η εντολή έπρεπε να πάει πρινQ=B*H*VWRITE (*, *) 'Παροχή Q:', QEND PROGRAM AGOG

Ο κώδικας με διορθώσεις είναι:

PROGRAM AGOGWRITE (*, *) 'Δώστε διαστάσεις διατομής b και h'READ (*, *) B, HS = 0.5/100.0AN = 0.015ABR = B * HPBR = B + 2.0 * HRH = ABR/PBRV = RH**(2.0/3.0)*SQRT(S)/ANQ = V * ABRWRITE (*, *) 'Παροχή Q:', QEND PROGRAM AGOG

Άσκηση Υπολογισμός Μέγιστης τάσηςΔεδομένα b, h, Μ

PROGRAM ANTOXWRITE (*, *) 'Δώστε διαστάσεις διατομής b και h'READ (*, *) B, HWRITE (*, *) 'Δώστε μέγιστη ροπή'READ (*, *) AMAI = B * H**3 / 12.0S = AM / AI * H / 2.0WRITE (*, *) 'Τάση σ:', SEND PROGRAM ANTOX

Άσκηση Πίνακας στροφώνΝα υπολογιστούν και να τυπωθούν τα στοιχεία του πίνακα στροφών με δεδομένα τις γωνίες ω, φ, κσε μοίρες.

[ cosφ cosκ cosω sinκ + sinω sinφ cosκ sinω sinκ – cosω sinφ cosκ ]R = [ cosφ sinκ cosω cosκ – sinω sinφ sinκ sinω cosκ + cosω sinφ sinκ ]

[ sinφ -sinω cosφ cosω cosφ ]

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 7

Page 8: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Κώδικας:

PROGRAM STROFWRITE (*, *) 'Δώστε ω, φ, κ σε μοίρες:'READ (*, *) W, F, AKPI = 3.14159W = W * PI / 180.0F = F * PI / 180.0AK = AK * PI / 180.0CF = COS(F)SF = SIN(F)CW = COS(W)SW = SIN(W)CK = COS(AK)SK = SIN(AK)R11 = CF * CKR12 = CW * SK + SW * SF * CKR13 = SW * SK – CW*SF*CKR21 = SF * SKR22 = CW * CK – SW * SF * SKR23 = SW * CK + CW * SF * SKR31 = SFR32 = -SW * CFR33 = CW * CFWRITE (*, *) R11, R12, R13WRITE (*, *) R21, R22, R23WRITE (*, *) R31, R32, R33END PROGRAM STROF

Υπολογισμός τριγωνομετρικών συναρτήσεων σε radΥπερφυσικές σταθερές (magic constants): 3.14159 (επίσης τι θα γινόταν αν είχαμε βάλει 3.14 καιμετά θέλαμε να το αλλάξουμε σε 3.14159).Υπολογισμός κάθε τριγωνομετρικής συνάρτησης 1 φορά για λόγους ταχύτητας καιαναγνωσιμότητας. Ονομασίες μεταβλητών έτσι ώστε η ονομασία να αντικατοπτρίζει την τιμή πουαποθηκεύουν οι μεταβλητές.

Άσκηση: Δημιουργία συνάρτησηςΔίνονται οι συναρτήσεις:f(x) = x – x3/3! + x5/5! - x7/7! + x9/9! - ...g(x) = 1 – x2/2! + x4/4! - x6/6! + x8/8! - ...

Να υπολογιστεί και να τυπωθεί το άθροισμα:f(ω) g(κ) + g(ω) g(φ) f(κ)όπου οι συναρτήσεις υπολογίζονται προσεγγιστικά με 4 όρους και τα ω,φ,κ δίνονται από τοπληκτρολόγιο.

f(x) = x – x3/3! + x5/5! = x(1 – x2/1 2 3 + x4/1 2 3 4 5 ) = x(1 + x2/1 2 3 (-1 + x2/4 5)) = x(1+x2/2 3 (-1 + x2/4 5)Ομοίως:g(x) = 1 – x2/2! + x4/4! = 1 – x2/2(-1 + x2/3 4 ) =1 – x2/2 (-1 + x2/3 4 )

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 8

Page 9: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Ορίζουμε συναρτήσεις:

MODULE MODFG CONTAINS

FUNCTION F(X)XX = X * XF = X*(1.0 + XX/6.0 * (-1.0 + XX/20.0 * (1.0 – XX/42.0)))F= X – X**3/(2.0*3.0) + X**5/(2.0*3.0*4.0*5.0) – X**7/( 2.0*3.0*4.0*5.0*6.0*7.0)A1 = XA2 = -A1*XX/(2.0*3.0)A3 = -A2*XX/(3.0*5.0)A4 = -A3*XX/(6.0*7.0)F = A1+A2+A3+A4END FUNCTION F

FUNCTION G(X)XX = X * XG = 1.0 – XX/2.0 * (-1.0 + XX/12.0 * (1.0 + XX/30.0))END FUNCTION G

END MODULE MODFG

Τώρα το άθροισμα είναι πολύ εύκολο:

PROGRAM S USE MODFG

READ (*, *) W, F, AKSUM = F(W)*G(AK) + G(W)*G(F)*F(AK)WRITE (*, *) SUMEND PROGRAM S

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 9

Page 10: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Δευτέρα 28/4/2014 10:45-14:30, B' πολ. Μηχανικών, Προγραμματισμός Η/Υ, θεωρία, Α Τμήμα (01AB) “Πράξεις” μεταξύ σταθερών κειμένου:Ένωση:'ΣΧΟΛΗ ' // 'ΕΜΠ' // 'ΑΘΗΝΑ' δίνει 'ΣΧΟΛΗ ΕΜΠΑΘΗΝΑ'Συμβολίζοντας τα κενά με ␣ διορθώνουμε την παράσταση:'ΣΧΟΛΗ␣' // 'ΕΜΠ␣' // ΑΘΗΝΑ' δίνει 'ΣΧΟΛΗ␣ΕΜΠ␣ΑΘΗΝΑ'Επιλογή υποκειμένου:'ΣΧΟΛΗ '(1:2) δίνει 'ΣΧ'␣'ΣΧΟΛΗ '(2:4) δίνει 'ΧΟΛ'␣'ΣΧΟΛΗ '(2:) δίνει 'ΧΟΛΗ ' (Δηλαδή παίρνει μέχρι το τέλος του κειμένου)␣ ␣'ΣΧΟΛΗ '(:4) δίνει 'ΣΧΟΛ' (Δηλαδή παίρνει από την αρχή του κειμένου)␣Μπορεί να γίνει μίξη ένωσης και επιλογής:'ΣΧΟΛΗ '(1:2) // ' . ' // 'ΕΜΠ '(:3) δίνει 'ΣΧ. ΕΜΠ'␣ ␣ ␣ ␣

Μεταβλητές κειμένου δηλώνονται με:CHARACTER(LEN=15) :: ASXOLHCHARACTER(LEN=20) :: AIDRYMA, AASXOLH = 'ΠΟΛ. ΜΗΧΑΝΙΚΩΝ' !Μπαίνουν κενά στο 15ο χαρακτήρα␣AIDRYMA = 'ΕΜΠ' !Μπαίνουν κενά από το 4ο ως τον 20ο χαρακτήραA = AIDRYMA // ' ' // ASXOLH !Δίνει 'ΕΜΠ ΠΟΛ.' (13 κενά)␣ ␣␣␣␣␣␣␣␣␣␣␣␣␣A = AIDRYMA(1:3) // ' ' // ASXOLH ! Δίνει 'ΕΜΠ ΠΟΛ. ΜΗΧΑΝΙΚΩΝ '␣ ␣ ␣ ␣

ΠαράδειγμαΝα υπολογιστεί ο μ.ο. από 6 μαθήματα ενός φοιτητή. Σε μία σειρά θα δοθούν:Επώνυμο, όνομα, βαθμός1, βαθμός2, βαθμός3, βαθμός4, βαθμός5, βαθμός6 Οι βαθμοί δίνονται ως ακέραιοι. Το όνομα και επώνυμο μπορεί να είναι μέχρι 30 χαρακτήρες. Ομ.ο. να υπολογιστεί ως πραγματικός. Επίσης από το επώνυμο να τυπωθούν μόνο μέχρι 10χαρακτήρες και από το όνομα μόνο μέχρι 3.

PROGRAM S INTEGER :: K1, K2, K3, K4, K5, K6 REAL :: AV CHARACTER(LEN=30) :: AEPON, AONOMA READ (*, *) EPON, ONOMA, K1, K2, K3, K4, L5, K6 AV = REAL(K1+K2+K3+K4+K5+K6) / 6.0 WRITE (*, *) EPON(1:10), ONOMA(1:3), AVEND PROGRAM S

Τα παραπάνω λάθη (EPON αντί AEPON, ONOMA αντί για AONOMA) θα επισημανθούν από τομεταγλωττιστή αφού α) σύμφωνα με τον έμμεσο κανόνα οι μεταβλητές EPON, ONOMA είναιπραγματικές β) η πράξεις EPON(1:10), AONOMA(1:3) δεν ισχύουν για πραγματικές μεταβλητές.Το επόμενο λάθος πληκτρολόγησης L5 αντί για K5 είναι συνηθισμένο (διότι τα K, L είναι γειτονικάστο πληκτρολόγιο), όμως ο μεταγλωττιστής δεν θα επισημάνει λάθος, αφού ισχύει ο έμμεσοςκανόνας που λέει ότι η μεταβλητή L5 είναι ακέραια και οι μεταβλητές K5, L5 χρησιμοποιούνται μεσωστό τρόπο. Για αυτό το λόγο θα πρέπει να πούμε στο μεταγλωττιστή να μην λαμβάνει αδήλωτεςμεταβλητές με τον έμμεσο κανόνα, αλλά να τυπώνει μηνύματα λάθους. Αυτό γίνεται με την εντολήIMPLICIT NONE:

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 10

Page 11: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

PROGRAM S IMPLICIT NONE INTEGER :: K1, K2, K3, K4, K5, K6 REAL :: AV CHARACTER(LEN=30) :: AEPON, AONOMA READ (*, *) EPON, ONOMA, K1, K2, K3, K4, L5, K6 AV = REAL(K1+K2+K3+K4+K5+K6) / 6.0 WRITE (*, *) EPON(1:10), ONOMA(1:3), AVEND PROGRAM S

Τώρα ο μεταγλωττιστής θα τυπώσει μήνυμα λάθους ότι η μεταβλητή L5 δεν έχει δηλωθεί, οπότε τοπρόγραμμα διορθώνεται σε:

PROGRAM S IMPLICIT NONE INTEGER :: K1, K2, K3, K4, K5, K6 REAL :: AV CHARACTER(LEN=30) :: AEPON, AONOMA READ (*, *) AEPON, AONOMA, K1, K2, K3, K4, K5, K6 AV = REAL(K1+K2+K3+K4+K5+K6) / 6.0 WRITE (*, *) AEPON(1:10), AONOMA(1:3), AVEND PROGRAM S

Ένα ακόμα θέμα είναι ότι μέχρι να βρεθεί το λάθος του προγράμματος πρέπει να γίνονται συνεχείςδοκιμές του προγράμματος δίνοντας από το πληκτρολόγιο το επώνυμο, όνομα και 6 βαθμούς σεκάθε δοκιμή. Αυτό είναι επίπονο και μπορούμε να το αποφύγουμε προσωρινά αλλάζοντας τηνεντολή READ έτσι ώστε να μην διαβάζει από το πληκτρολόγιο αλλά από από μία μεταβλητήχαρακτήρων, η οποία περιέχει αυτά που θα δίναμε από το πληκτρολόγιο, δηλαδή το επώνυμο, τοόνομα και τους 6 βαθμούς με ένα ή περισσότερα διαχωριστικά κενά ανάμεσά τους:

PROGRAM S IMPLICIT NONE INTEGER :: K1, K2, K3, K4, K5, K6 REAL :: AV CHARACTER(LEN=30) :: AEPON, AONOMA CHARACTER(LEN=80) :: A A = 'Παπαδάκης␣Μανώλης␣␣6␣␣5␣␣8␣␣7␣␣8␣␣5' READ (A, *) AEPON, AONOMA, K1, K2, K3, K4, K5, K6 AV = REAL(K1+K2+K3+K4+K5+K6) / 6.0 WRITE (*, *) AEPON(1:10), AONOMA(1:3), AVEND PROGRAM S

Μόλις εξακριβωθεί ότι το πρόγραμμα λειτουργεί σωστά, αλλάζουμε ξανά την εντολή READ έτσιώστε να διαβάζει από το πληκτρολόγιο.

MODULESΣύμφωνα με το πρότυπο της Fortran95 τα υποπρογράμματα (οι συναρτήσεις και υπορουτίνες πουθα πούμε παρακάτω) ομαδοποιούνται σε λειτουργικές ενότητες: modules. Η module συντάσσεται:

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 11

Page 12: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

MODULE module_name IMPLICIT NONE CONTAINS

FUNCTION ... .... END FUNCTION ...

FUNCTION ... .... END FUNCTION ...

END MODULE

Η εντολή IMPLICIT NONE ισχύει για όλες τις συναρτήσεις και υπορουτίνες (υποπρογράμματα)της module και δεν χρειάζεται να τη γράφουμε σε κάθε υποπρόγραμμα. Μία module μπορεί ναχρησιμοποιηθεί από το κύριο πρόγραμμα (ή και ένα υποπρόγραμμα) με την εντολή USE:

PROGRAM ... USE MODULE_NAME IMPLICIT NONE ... END PROGRAM

Ας σημειωθεί ότι το κύριο πρόγραμμα δεν μπορεί να είναι μέσα σε μία module.

Άσκηση: Να υπολογιστεί ο συντελεστής τριβής για κλειστούς αγωγούςΔίνεται ο αναδρομικός τύπος:1/sqrt(fn+1) = -2log10(k/D / 3.71 + 2.51/(Re sqrt(fn)))

1

√ f n+1

= −2 log10( k /D3.71+

2.51Re √ f n )

Από εγχειρίδιο υδραυλικής αν ο τύπος εφαρμοστεί 4 φορές με αρχική τιμή f0=0.002 τότε έχειβρεθεί ο συντελεστής τριβής με ικανοποιητική ακρίβεια. Να υπολογιστεί το f για k/D και Re:0.001 1500000.0005 2000000.002 150000

Για να κάνουμε πιο εύκολους τους υπολογισμούς μετατρέπουμε τον τύπο σε πιο εύχρηστη μορφή:

f n+1 =1

[2 log10( k /D3.71+

2.51Re √ f n )]

2

Απευθείας μετάφραση σε πρόγραμμα δίνει (προσοχή: οι φοιτητές δεν έχουν την υπομονή για αυτήτην επανάληψη και μπερδεύονται παρακάτω όταν δημιουργείται και δεύτερη συνάρτηση: στηναίθουσα να γίνει απευθείας η λύση με συνάρτηση).

Κώδικας:

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 12

Page 13: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

PROGRAM S IMPLICIT NONE REAL :: AKD, RE, A, B, C, D, E AKD = 0.001 RE = 150000.0 A = 0.002 B = 1.0/(2.0 * ALOG10(AKD/3.71 + 2.51/(RE*SQRT(A))))**2 C = 1.0/(2.0 * ALOG10(AKD/3.71 + 2.51/(RE*SQRT(B))))**2 D = 1.0/(2.0 * ALOG10(AKD/3.71 + 2.51/(RE*SQRT(C))))**2 E = 1.0/(2.0 * ALOG10(AKD/3.71 + 2.51/(RE*SQRT(D))))**2 WRITE (*, *) AKD, RE, E

AKD = 0.0005 RE = 200000.0 A = 0.002 B = 1.0/(2.0 * ALOG10(AKD/3.71 + 2.51/(RE*SQRT(A))))**2 C = 1.0/(2.0 * ALOG10(AKD/3.71 + 2.51/(RE*SQRT(B))))**2 D = 1.0/(2.0 * ALOG10(AKD/3.71 + 2.51/(RE*SQRT(C))))**2 E = 1.0/(2.0 * ALOG10(AKD/3.71 + 2.51/(RE*SQRT(D))))**2 WRITE (*, *) AKD, RE, E

AKD = 0.002 RE = 150000.0 A = 0.002 B = 1.0/(2.0 * ALOG10(AKD/3.71 + 2.51/(RE*SQRT(A))))**2 C = 1.0/(2.0 * ALOG10(AKD/3.71 + 2.51/(RE*SQRT(B))))**2 D = 1.0/(2.0 * ALOG10(AKD/3.71 + 2.51/(RE*SQRT(C))))**2 E = 1.0/(2.0 * ALOG10(AKD/3.71 + 2.51/(RE*SQRT(D))))**2 WRITE (*, *) AKD, RE, EEND PROGRAM S

Παρατηρούμε την επανάληψη του κώδικα που υπολογίζει το συντελεστή τριβής. Η επανάληψηείναι επίπονη αλλά κυρίως είναι επιρρεπής σε λάθη. Τοποθετούμε τον κοινό κώδικα σε συνάρτηση:

MODULE MODTRIBIMPLICIT NONECONTAINS

REAL FUNCTION TRIB(AKD, RE) REAL :: AKD, RE REAL :: A, B, C, D, E A = 0.002 B = 1.0/(2.0 * ALOG10(AKD/3.71 + 2.51/(RE*SQRT(A))))**2 C = 1.0/(2.0 * ALOG10(AKD/3.71 + 2.51/(RE*SQRT(B))))**2 D = 1.0/(2.0 * ALOG10(AKD/3.71 + 2.51/(RE*SQRT(C))))**2 E = 1.0/(2.0 * ALOG10(AKD/3.71 + 2.51/(RE*SQRT(D))))**2 TRIB = EEND FUNCTION TRIB

END MODULE MODTRIB

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 13

Page 14: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

PROGRAM S USE MODTRIB IMPLICIT NONE WRITE (*, *) 0.001, 150000.0, TRIB(0.001, 150000.0) WRITE (*, *) 0.0005, 200000.0, TRIB(0.0005, 200000.0) WRITE (*, *) 0.002, 150000.0, TRIB(0.002, 150000.0)END PROGRAM S

Παρατηρούμε την επανάληψη του κώδικα που υπολογίζει το συντελεστή τριβής. Η επανάληψη είναι επίπονη αλλά κυρίως είναι επιρρεπής σε λάθη. Τοποθετούμε τον κοινό κώδικα σε δεύτερη συνάρτηση. (ΠΡΟΣΟΧΗ: ΟΙ ΦΟΙΤΗΤΕΣ ΜΠΕΡΔΕΥΟΝΤΑΙ ΣΕ ΑΥΤΟ ΤΟ ΣΗΜΕΙΟ αν στην αίθουσα έχει δοθεί και η λύση χωρίς καθόλου συναρτήσεις):

MODULE MODTRIBIMPLICIT NONECONTAINS

REAL FUNCTION TRIB(AKD, RE) REAL :: AKD, RE REAL :: A, B, C, D, E A = 0.002 B = TYPOS(AKD, RE, A) C = TYPOS(AKD, RE, B) D = TYPOS(AKD, RE, C) E = TYPOS(AKD, RE, D) TRIB = EEND FUNCTION TRIB

REAL FUNCTION TYPOS(AKD, RE, A) REAL :: AKD, RE, A TYPOS = 1.0/(2.0 * ALOG10(AKD/3.71 + 2.51/(RE*SQRT(A))))**2END FUNCTION TYPOS

END MODULE MODTRIB

PROGRAM S USE MODTRIB IMPLICIT NONE WRITE (*, *) 0.001, 150000.0, TRIB(0.001, 150000.0) WRITE (*, *) 0.5E-3, 200.0E3, TRIB(0.5E-3, 200.0E3) WRITE (*, *) 2.0E-3, 150.0E3, TRIB(2.0E-3, 150.0E3)END PROGRAM S

Παρατηρούμε ότι ενώ αλλάξαμε την συνάρτηση TRIB, το κύριο πρόγραμμα που καλεί την TRIBδεν άλλαξε καθόλου. Αυτός είναι ένας ακόμα σημαντικός λόγος να χρησιμοποιούνται συναρτήσεις.Αν στο μέλλον ανακαλυφθεί μία καλύτερη μέθοδος (για παράδειγμα πιο ακριβής, ή πιο γρήγορη) τομόνο που πρέπει να αλλάξει είναι η συνάρτηση TRIB που είναι (10-20 γραμμές κώδικα (Lines OfCode – LOC), ενώ το κύριο πρόγραμμα που ενδεχομένως είναι χιλιάδες LOC δεν χρειάζεται νααλλάξει καθόλου.

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 14

Page 15: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

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

Διευκρίνηση μεταξύ 3.14E2 και 3.14 * 10**2.1. 3.14E2 είναι μία σταθερά και είναι απλώς (και τίποτε άλλο) μία συντομογραφία του

31400.0 και ο υπολογιστής δεν ξοδεύει χρόνο για να υπολογίσει κάτι. Είναι μία σύμβασηγια μην χρειάζεται να γράψουμε πολλά μηδενικά. Επίσης είτε γραφεί 3.14E2 είτε 31400.0 ομεταγλωττιστής (compiler) θα παράγει ακριβώς τον ίδιο κώδικα μηχανής.

2. 3.14 * 10.0**4 είναι μία αριθμητική παράσταση που αποτελείται από 2 πράξεις καιχρειάζεται χρόνο για να υπολογιστεί.

3. 3.14E4.3 είναι συντακτικό λάθος γιατί το πρότυπο της Fortran απαιτεί ο αριθμός μετά το Eνα είναι ακέραιος. Ο μόνος τρόπος είναι με αριθμητική παράσταση: 3.14 * 10.0**4.3 ηοποία απαιτεί πολλές δεκάδες πράξεων (λόγω έμμεσου υπολογισμού της EXP(X) καιALOG(X)) και χρειάζεται χρόνο για να υπολογιστεί.

Η παρακάτω προσέγγιση για την επίλυση του προβλήματος θεωρήθηκε δυσνόητη από τους φοιτητές:Έστω η συνάρτηση:g(x, kD, Re) = {1/[2log10(k/D / 3,71 + 2,51/(Re sqrt(x)))]}2 Τότε:fn+1 = g(fn, kD, Re)Οπότε για να βρούμε το συντελεστή τριβής για k/D=0.001 και Re=150000:

f1 = g(f0, 0.001, 150000)f2 = g(f1, 0.001, 150000)f3 = g(f2, 0.001, 150000)f4 = g(f3, 0.001, 150000)

G = 1.0/(2.0 * ALOG10(AKD/3.71 + 2.51/(RE*SQRT(F1))))**2

PROGRAM S AKD = 0.001 RE = 150000.0 A = 0.002 B = 1.0/(2.0 * ALOG10(AKD/3.71 + 2.51/(RE*SQRT(A))))**2

C = 1.0/(2.0 * ALOG10(AKD/3.71 + 2.51/(RE*SQRT(B))))**2D = 1.0/(2.0 * ALOG10(AKD/3.71 + 2.51/(RE*SQRT(C))))**2E = 1.0/(2.0 * ALOG10(AKD/3.71 + 2.51/(RE*SQRT(C))))**2

A = G(0.002, AKD, RE) B = G(A, AKD, RE) C = G(B, AKD, RE) D = G(D, AKD, RE)

WRITE (*, *) AKD, RE, D AKD = 0.005 RE = 200000.0 A = G(0.002, AKD, RE) B = G(A, AKD, RE) C = G(B, AKD, RE) D = G(D, AKD, RE)

WRITE (*, *) AKD, RE, D AKD = 0.002 RE = 150000.0 A = G(0.002, AKD, RE) B = G(A, AKD, RE) C = G(B, AKD, RE) D = G(D, AKD, RE)

WRITE (*, *) AKD, RE, DSTOPEND

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 15

Page 16: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

FUNCTION G(F0, AKD, RE)G = 1.0/(2.0 * ALOG10(AKD/3.71 + 2.51/(RE*SQRT(F1))))**2RETURNEND

Παρατηρούμε επαναλαμβανόμενο κώδικα, ο οποίος μπορεί να οδηγήσεις σε λάθη (είτε ανθρώπινα λάθη κατά το γράψιμο ή αναλλάξουμε τον κώδικα, πρέπει να το κάνουμε 4 φορές και μπορεί να το ξεχάσουμε μία φορά). Το επαναλαμβανόμενο κώδικα τονγράφουμε σε ξεχωριστή συνάρτηση:

FUNCTION H(AKD, RE) A = G(0.002, AKD, RE) B = G(A, AKD, RE) C = G(B, AKD, RE) D = G(D, AKD, RE) H = D RETURN

END

Έτσι το πρόγραμμα γράφεται τώρα:

PROGRAM SWRITE (*, *) 0.001, 150000.0, Η(0.001, 150000.0)WRITE (*, *) 0.0005, 200000.0, Η(0.0001, 200000.0)WRITE (*, *) 0.002, 150000.0, Η(0.002, 150000.0)STOPEND

Άσκηση (για το σπίτι)Δίνονται οι συναρτήσεις:f(x) = (5x2+3x+11) / (18x2-10x+3)g(x) = (ex + e-x) / 2Να υπολογιστεί: f(x), g(x), f(x)+g(x), f(x) g(x), f[g(x)]για x=10, -1, 3.1415

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 16

Page 17: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Εντολές διακλάδωσηςΗ πιο απλή μορφή της εντολής IF στη Fortran είναι:

IF (συνθήκη) THENεντολή α1εντολή α2

........... END IF

εντολή β1εντολή β2

...........Αν η συνθήκη είναι αληθής τότε εκτελούνται οι εντολές α1, α2, κλπ που βρίσκονται μεταξύ τουTHEN και του END IF, και αμέσως μετά οι εντολές β1, β2 κλπ. που βρίσκονται μετά από το ENDIF. Αν είναι ψευδής ΔΕΝ εκτελούνται οι εντολές α1, α2, κλπ που βρίσκονται μεταξύ του THEN καιτου END IF, αλλά απευθείας οι εντολές β1, β2 κλπ. Που βρίσκονται μετά από το END IF.

Η συνθήκη συντάσσεται:παράσταση1 τελεστής παράσταση2

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

.EQ. ή == (EQual)

.NE. ή /= (Not Equal)

.GT. ή > (Greater Than)

.LT. ή < (Lower Than)

.GE. ή <= (Greater or Equal)

.LE. ή >= (Lower or Equal)

ΠαράδειγμαΝα συντάξετε πρόγραμμα που να υπολογίζει την απόλυτη τιμή τριών πραγματικών αριθμών πουδίνονται από το πληκτρολόγιο (χωρίς τη χρήση της έτοιμης συνάρτησης ABS)..

PROGRAM AT1 IMPLICIT NONE REAL :: A, B, C READ (*, *) A, B, C IF (A .LT. 0.0) THEN A = -A END IF IF (B .LT. 0.0) THEN B = -B END IF IF (C .LT. 0.0) THEN C = -A END IF WRITE (*, *) A, B, CEND PROGRAM AT1

Προσέξτε το πολύ συνηθισμένο λάθος (A αντί για C) που οφείλεται στην επίπονη επανάληψη

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 17

Page 18: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

παρόμοιου κώδικα (στην ουσία κάνουμε αντιγραφή και επικόλληση του κώδικα πουεπαναλαμβάνεται και αλλάζουμε τις ονομασίες των μεταβλητών: στην τρίτη περίπτωση εκπαραδρομής δεν αλλάξαμε την A σε C). Το λάθος αυτό αποφεύγεται αν δεν κάνουμε επίπονηεπανάληψη παρόμοιου κώδικα χρησιμοποιώντας συναρτήσεις, τις οποίες θα χρησιμοποιούμε απότην αρχή από εδώ και πέρα. Με συνάρτηση το πρόγραμμα απλουστεύεται:

MODULE MODAPOLIMPLICIT NONECONTAINS

REAL FUNCTION APOL(X) REAL :: X REAL :: B APOL = X IF (APOL < 0.0) THEN APOL = -X END IFEND FUNCTION APOL

END MODULE MODAPOL

PROGRAM AT2 USE MODAPOL IMPLICIT NONE REAL :: A, B, C READ (*, *) A, B, C WRITE (*, *) APOL(A), APOL(B), APOL(C)END PROGRAM AT2

Συντομογραφία (χωρίς ELSE και μόνο ΜΙΑ εντολή εντός του IF)Η παρακάτω δομή επανάληψης:

IF (συνθήκη) THENεντολή α1 (μόνο μία εντολή)

END IFεντολή β1εντολή β2

...........

μπορεί να συντομευθεί στην

IF (συνθήκη) εντολή α1 (μόνο μία εντολή)εντολή β1εντολή β2

...........

Αν η συνθήκη είναι αληθής τότε εκτελείται η εντολή α1 και μετά η εντολή β1, β2 κλπ. Αν είναιψευδής τότε ΔΕΝ εκτελείται η εντολή α1, αλλά εκτελείται απευθείας η εντολή β1, β2 κλπ. Δηλαδήη εντολή β1, β2 κλπ εκτελείται έτσι και αλλιώς, είτε η συνθήκη είναι αληθής είτε είναι ψευδής.

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 18

Page 19: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

ΠαράδειγμαΕφαρμογή της συντομογραφίας στο προηγούμενο παράδειγμα δίνει:

MODULE MODAPOLIMPLICIT NONECONTAINS

REAL FUNCTION APOL(X) REAL :: X APOL = X IF (APOL < 0.0) APOL = -XEND FUNCTION APOL

END MODULE MODAPOL

PROGRAM AT2 USE MODAPOL IMPLICIT NONE REAL :: A, B, C READ (*, *) A, B, C WRITE (*, *) APOL(A), APOL(B), APOL(C)END PROGRAM AT2

Η εντολή IF μπορεί να καθορίσει τι να εκτελεστεί στην περίπτωση που η συνθήκη δεν είναιαληθής

IF (συνθήκη) THENεντολή α1εντολή α2

........... ELSE

εντολή β1εντολή β2

........... END IF

εντολή γ1εντολή γ2

...........

Αν η συνθήκη είναι αληθής τότε εκτελούνται οι εντολές α1, α2, κλπ που βρίσκονται μεταξύ τουTHEN και του ELSE, και αμέσως μετά οι εντολές γ1, γ2 κλπ. που βρίσκονται μετά από το END IF.Αν είναι ψευδής τότε εκτελούνται οι εντολές β1, β2, κλπ που βρίσκονται μεταξύ του ELSE και τουEND IF, και αμέσως μετά οι εντολές β1, β2 κλπ. που βρίσκονται μετά από το END IF.

ΠαράδειγμαΝα επιλυθεί η πρωτοβάθμια εξίσωση ax+b=0 με διερεύνηση αν a=0.

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 19

Page 20: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

PROGRAM EX1 IMPLICIT NONE REAL :: A, B, X READ (*, *) A, B IF (A == 0.0) THEN WRITE (*, *) 'Αδύνατη/αόριστη εξίσωση' ELSE X = -B/A WRITE (*, *) X END IFEND PROGRAM EX1

Σε γραφική μορφή, ή διάγραμμα ροής, ο παραπάνω κώδικας δίνεται:

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 20

Page 21: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 21

Page 22: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Η εντολή IF μπορεί να έχει πολλαπλές συνθήκες:IF (συνθήκη α) THEN

εντολή α1εντολή α2

........... ELSE IF (συνθήκη β) THEN

εντολή β1εντολή β2

........... ELSE IF (συνθήκη γ) THEN

εντολή γ1εντολή γ2

........... ELSE IF (συνθήκη δ) THEN

εντολή δ1εντολή δ2

........... ELSE

εντολή ε1εντολή ε2

........... END IF

εντολή ζ1εντολή ζ2

...........

Η εκτέλεση του προγράμματος γίνεται σε βήματα που καθορίζονται από τις συνθήκες:1. Αν η συνθήκη α είναι αληθής τότε εκτελούνται οι εντολές α1, α2, κλπ που βρίσκονται μεταξύ τουIF (συνθήκη α) και του ELSE IF (συνθήκη β) , και αμέσως μετά οι εντολές ζ1, ζ2 κλπ. πουβρίσκονται μετά από το END IF.2. Αν η συνθήκη α είναι ψευδής, τότε αν η συνθήκη β είναι αληθής τότε εκτελούνται οι εντολές β1,β2, κλπ που βρίσκονται μεταξύ του IF (συνθήκη β) και του ELSE IF (συνθήκη γ), και αμέσως μετάοι εντολές ζ1, ζ2 κλπ. που βρίσκονται μετά από το END IF.3. Αν η συνθήκη β είναι ψευδής, τότε αν η συνθήκη γ είναι αληθής τότε εκτελούνται οι εντολές γ1,γ2, κλπ που βρίσκονται μεταξύ του IF (συνθήκη γ) και του ELSE IF (συνθήκη δ), και αμέσως μετάοι εντολές ζ1, ζ2 κλπ. που βρίσκονται μετά από το END IF.4. Αν η συνθήκη γ είναι ψευδής, τότε αν η συνθήκη δ είναι αληθής τότε εκτελούνται οι εντολές δ1,δ2, κλπ που βρίσκονται μεταξύ του IF (συνθήκη γ) και του ELSE, και αμέσως μετά οι εντολές ζ1,ζ2 κλπ. που βρίσκονται μετά από το END IF.5. Τέλος αν η συνθήκη δ είναι ψευδής, τότε εκτελούνται οι εντολές ε1, ε2, κλπ που βρίσκονταιμεταξύ του ELSE και του END IF, και αμέσως μετά οι εντολές ζ1, ζ2 κλπ. που βρίσκονται μετάαπό το END IF.

Το τελευταίο ELSE είναι προαιρετικό. Αν δεν υπάρχει τότε το 5ο βήμα γίνεται ως εξής:5. Τέλος αν η συνθήκη δ είναι ψευδής, τότε εκτελούνται οι εντολές ζ1, ζ2 κλπ. που βρίσκονται μετάαπό το END IF, δηλαδή δεν εκτελείται καμία από τις εντολές που υπάρχουν μεταξύ IF και END IF.

Ας σημειωθεί ότι για να φτάσει το πρόγραμμα να ελέγξει αν μία συνθήκη (πχ η συνθήκη γ) είναι

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 22

Page 23: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

αληθής, πρέπει υποχρεωτικά όλες οι προηγούμενες συνθήκες (α και β) να είναι ψευδείς, αλλιώς τοπρόγραμμα δεν θα έφτανε ποτέ εκεί. Αυτό μπορεί να έχει απρόσμενες συνέπειες αν οι συνθήκεςείναι επικαλυπτόμενες, όπως στον κώδικα που ακολουθεί:

IF (K > 0) THEN WRITE (*, *) 'ΘΕΤΙΚΟΣ'ELSE IF (K < 0) THEN WRITE (*, *) 'ΑΡΝΗΤΙΚΟΣ'ELSE IF (K > 1000000) THEN WRITE (*, *) 'ΤΕΡΑΣΤΙΟΣ'ELSE WRITE (*, *) 'ΜΗΔΕΝ'END IF

Το πρόγραμμα δεν θα τυπώσει ποτέ το 'ΤΕΡΑΣΤΙΟΣ'. Αν k=2000000, τότε K>0 και το πρόγραμμαθα τυπώσει 'ΘΕΤΙΚΟΣ' και αμέσως μετά θα συνεχίζει μετά το END IF. Για να λειτουργήσει σωστάο κώδικας πρέπει να γίνει:

F (K > 1000000) THEN WRITE (*, *) 'ΤΕΡΑΣΤΙΟΣ'ELSE IF (K > 0) THEN WRITE (*, *) 'ΘΕΤΙΚΟΣ'ELSE IF (K < 0) THEN WRITE (*, *) 'ΑΡΝΗΤΙΚΟΣ'ELSE WRITE (*, *) 'ΜΗΔΕΝ'END IF

ΠαράδειγμαΝα επιλυθεί η δευτεροβάθμια εξίσωση αx2+βx+γ=0, θεωρώντας ότι a≠0.Η εξίσωση έχει δύο πραγματικές ρίζες, μία διπλή ρίζα ή 2 συζυγείς μιγαδικές ρίζες ανάλογα με αν ηδιακρίνουσα Δ = β2-4αγ είναι μεγαλύτερη, ίση, ή μικρότερη από μηδέν.

PROGRAM DEYT IMPLICIT NONE REAL :: A, B, G, D, X1, X2, P, F READ (*, *) A, B, G IF (A .EQ. 0.0) THEN WRITE (*, *) 'ΕΠΡΕΠΕ Α <> 0.0' STOP END IF D = B**2 - 4.0*A*G IF (D .EQ. 0.0) THEN WRITE (*, *) 'ΔΙΠΛΗ ΡΙΖΑ X=', -B/(2.0*A) ELSE IF (D .GT. 0.0) THEN X1 = (-B + SQRT(D)) / (2.0*A) X2 = (-B - SQRT(D)) / (2.0*A) WRITE (*,*)'ΠΡΑΓΜΑΤΙΚΕΣ ΡΙΖΕΣ X1=', X1, ' X2=', X2 ELSE P = -B / (2.0*A) F = SQRT(-D) / (2.0*A)

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 23

Page 24: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

WRITE (*, *) 'ΜΙΓΑΔΙΚΕΣ ΡΙΖΕΣ X1=', P, '+', F, 'i' WRITE (*, *) ' X2=', P, '-', F, 'i' END IFEND PROGRAM DEYT

Εμφωλευμένα IF. Η δομή IF ... THEN .... ELSE IF .... ELSE... END λέγεται block if. Ένα block if (εσωτερικό) μπορείνα είναι μέσα σε ένα άλλο (εξωτερικό), αλλά πρέπει να είναι εξολοκλήρου μεταξύ μέσα σε ένακλάδο του εξωτερικού block if. Δηλαδή πρέπει να είναι εξολοκλήρου μεταξύ THEN και τουκοντινότερου ELSE, ή ELSE IF, ή END IF του εξωτερικού. Γραφικά, χαράσσουμε καμπύλεςγραμμές μεταξύ του IF, ELSE IF, ELSE και END IF για να ξεχωρίσουμε τους κλάδους του block if.Οι γραμμές του εσωτερικού και του εξωτερικού block if δεν πρέπει να τέμνονται:

Σε αυτό το παράδειγμα οι κόκκινες με τις μπλε γραμμές δεν πρέπει να τέμνονται.Ας σημειωθεί ότι για να καταλάβουμε αν κάποιο IF είναι εμφωλευμένο στο εξωτερικό block if καιόχι μέρος του εξωτερικού block if, παρατηρούμε ότι το εσωτερικό block if αρχίζει με την εντολή IFκαι ο με την εντολή ELSE IF.

ΆσκησηΝα υπολογιστούν οι ρίζες της δευτεροβάθμιας εξίσωσης Ax2 + Bx + Γ = 0 λαμβάνοντας υπόψηόλες τις δυνατές περιπτώσεις. Οι συντελεστές Α, Β και Γ είναι πραγματικοί αριθμοί.

ΑνάλυσηΟι διάφορες περιπτώσεις ανάγονται στο μηδενισμό των διάφορων συντελεστών. Έτσι:α. Αν Α=Β=0 τότε η εξίσωση δεν έχει νόημα γιατί δεν υπάρχουν άγνωστες ποσότητες.β. Αν Α=0 και Β≠0 τότε η εξίσωση είναι πρωτοβάθμια και έχει μία λύση: x=-Γ/Βγ. Αν Α <>0 τότε η εξίσωση είναι δευτεροβάθμια και έχει 1 ή 2 πραγματικές ρίζες, ή 2 συζυγείς

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 24

Page 25: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

μιγαδικές ρίζες. Συγκεκριμένα αν η διακρίνουσα Δ = Β2 – 4 Α Γ είναι:

•Δ > 0: Δύο πραγματικές ρίζες x1,2=−Β±√Δ

2A

•Δ = 0: Μία πραγματική ρίζα x=−Β

2A

•Δ < 0: Δύο συζυγείς μιγαδικές ρίζες x1,2=−Β

2A±i √−Δ

2A

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

Κώδικας:

PROGRAM DEYT2 IMPLICIT NONE REAL :: A, B, G, D, X1, X2, P, F READ (*, *) A, B, G IF (A .EQ. 0.0) THEN IF (B .EQ. 0.0) THEN WRITE (*, *) 'ΔΕΝ ΕΙΝΑΙ ΕΞΙΣΩΣΗ' ELSE WRITE (*, *) 'ΠΡΩΤΟΒΑΘΜΙΑ ΕΞΙΣΩΣΗ ΡΙΖΑ X=', -G/B END IF ELSE D = B**2 - 4.0*A*G IF (D .EQ. 0.0) THEN WRITE (*, *) 'ΔΙΠΛΗ ΡΙΖΑ X=', -B/(2.0*A) ELSE IF (D .GT. 0.0) THEN X1 = (-B + SQRT(D)) / (2.0*A) X2 = (-B - SQRT(D)) / (2.0*A) WRITE (*,*)'ΠΡΑΓΜΑΤΙΚΕΣ ΡΙΖΕΣ X1=', X1, ' X2=', X2 ELSE P = -B / (2.0*A) F = SQRT(-D) / (2.0*A) WRITE (*, *) 'ΜΙΓΑΔΙΚΕΣ ΡΙΖΕΣ X1=', P, '+', F, 'i' WRITE (*, *) ' X2=', P, '-', F, 'i' END IF END IFEND PROGRAM DEYT2(Στην αίθουσα εξήγηση εμφωλευμένων IF παραπάνω).

Ο κώδικας γίνεται πιο κατανοητός αν χρησιμοποιήσουμε συναρτήσεις:

MODULE MODEXIMPLICIT NONECONTAINS

REAL FUNCTION PROTOB(B, G) REAL :: B, G IF (B == 0.0) THEN WRITE (*, *) 'ΔΕΝ ΕΙΝΑΙ ΕΞΙΣΩΣΗ'

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 25

Page 26: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

ELSE WRITE (*, *) 'ΠΡΩΤΟΒΑΘΜΙΑ ΕΞΙΣΩΣΗ ΡΙΖΑ X=', -G/B END IF PROTOB = 0.0END FUNCTION PROTOB

REAL FUNCTION DEYTEROB(A, B, G) REAL :: A, B, G REAL :: D, X1, X2, P, F D = B**2 - 4.0*A*G IF (D == 0.0) THEN WRITE (*, *) 'ΔΙΠΛΗ ΡΙΖΑ X=', -B/(2.0*A) ELSE IF (D > 0.0) THEN X1 = (-B + SQRT(D)) / (2.0*A) X2 = (-B - SQRT(D)) / (2.0*A) WRITE (*,*)'ΠΡΑΓΜΑΤΙΚΕΣ ΡΙΖΕΣ X1=', X1, ' X2=', X2 ELSE P = -B / (2.0*A) F = SQRT(-D) / (2.0*A) WRITE (*, *) 'ΜΙΓΑΔΙΚΕΣ ΡΙΖΕΣ X1=', P, '+', F, 'i' WRITE (*, *) ' X2=', P, '-', F, 'i' END IF DEYTEROB = 0.0END FUNCTION DEYTEROB

END MODULE MODEX

PROGRAM DEYT2 USE MODEX IMPLICIT NONE REAL :: A, B, G, TEMP READ (*, *) A, B, G IF (A .EQ. 0.0) THEN TEMP = PROTOB(B, G) ELSE TEMP = DEYTEROB(A, B, G) END IFEND PROGRAM DEYT2

Δηλαδή φτιάχνουμε συναρτήσεις και για έναν ακόμα λόγο. Για να διασπάσουμε το πρόγραμμα σεμικρότερα και πιο κατανοητά τμήματα. Ένα ακόμα πλεονέκτημα είναι οι οι μεταβλητές D, X1, X2,P, F δεν δηλώνονται στη συνάρτηση PROTOB διότι δεν χρειάζονται, και έτσι αν κατά λάθος γράψεικανείς D αντί για B, ο μεταγλωττιστής θα επισημάνει το λάθος.

Σε διάγραμμα ροής η επίλυση της δευτεροβάθμιας εξίσωσης δίνεται παρακάτω.

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 26

Page 27: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 27

Page 28: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

ΠαράδειγμαΔοκός καταπονείται από συγκεντρωμένο φορτίο P στο μέσο και ομοιόμορφο φορτίο q. Ναυπολογιστεί και να τυπωθεί η καμπτική ροπή στις θέσεις: x=0, L/4, L/2, 3L/4, LΔίνεται ότι για δοκό υπό ομοιόμορφο φορτίο:

M(x) = qL/2 x – q x2/2και για δοκό με συγκεντρωμένο φορτίο στο μέσο:

M(x) = P/2 x x≤L/2M(x) = P/2 x – P(x-L/2) x>L/2

ΑνάλυσηΑπό την αρχή της επαλληλίας η καμπτική ροπή είναι το άθροισμα της ροπής για ομοιόμορφοφορτίο συν τη ροπή για συγκεντρωμένο φορτίο:

M(x) = qL/2 x – q x2/2 + P/2 x x≤L/2M(x) = qL/2 x – q x2/2 + P/2 x – P(x-L/2) x>L/2

Κώδικας

MODULE MODMIMPLICIT NONECONTAINS

REAL FUNCTION AM(P, Q, AL, X) REAL :: P, Q, AL, X IF (X <= AL/2.0) THEN AM = P*0.5*X + Q*AL*0.5*X - Q*0.5*X**2 ELSE AM = P*0.5*X + Q*AL*0.5*X - Q*0.5*X**2 - P*(X-AL*0.5) END IFEND FUNCTION AM

END MODULE MODM

PROGRAM KAM USE MODM IMPLICIT NONE REAL :: P, Q, AL READ (*, *) P, Q, AL WRITE (*, *) AM(P, Q, AL, 0.0) WRITE (*, *) AM(P, Q, AL, AL*0.25) WRITE (*, *) AM(P, Q, AL, AL*0.5) WRITE (*, *) AM(P, Q, AL, AL*0.75) WRITE (*, *) AM(P, Q, AL, AL)END PROGRAM KAM

(Στην αίθουσα εξήγηση των δύο AL στην τελευταία κλήση της συνάρτησης).

Παρατηρούμε ότι για x>L/2 η ροπή είναι ότι και για x≤L/2 συν ένα ακόμα όρο. Αυτή είναι ηιδανική περίπτωση για εφαρμογή της συντομογραφίας στο IF. Ο κώδικας γίνεται μικρότερος καιπιο ευανάγνωστος:

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 28

Page 29: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

REAL FUNCTION AM(P, Q, AL, X) REAL :: P, Q, AL, X AM = P*0.5*X + Q*AL*0.5*X - Q*0.5*X**2 IF (X > AL/2.0) AM = AM - P*(X-AL*0.5)END FUNCTION AM

Κοινές μεταβλητές σε συναρτήσεις μίας ενότητας (module)Παρατηρούμε ότι σε όλες τις κλήσεις της συνάρτησης ΑΜ() επαναλαμβάνονται οι μεταβλητές P,Q, AL, οι οποίες είναι στην ουσία οι ίδιες με αυτές του κυρίου προγράμματος. Γενικώς μίαμεταβλητή στο κύριο πρόγραμμα που έχει το ίδιο όνομα με μία μεταβλητή σε ένα υποπρόγραμμαδεν είναι ίδιες (έχουν ίδιο όνομα αλλά άλλο “επώνυμο”), διότι αλλιώς θα επικρατούσε χάος αφούτο κύριο πρόγραμμα και το κάθε υποπρόγραμμα μπορεί να γραφεί από διαφορετικό μηχανικό,και οκαθένας να τύχει να χρησιμοποιήσει το ίδιο όνομα μεταβλητής για να αποθηκεύσει τελείωςδιαφορετικές ποσότητες. Σε αρκετές περιπτώσεις όμως όπως και σε αυτό το παράδειγμα, μερικέςμεταβλητές είναι όντως ίδιες μεταξύ του προγράμματος και του υποπρογράμματος. Η Fortranεπιτρέπει σε αυτές τις περιπτώσεις να ορίσουμε ότι αυτές οι μεταβλητές είναι κοινές μεταξύ τουπρογράμματος και υποπρογράμματος, δηλώνοντας αυτές τις μεταβλητές όχι στο κύριο πρόγραμμα,ούτε στο υποπρόγραμμα, αλλά στην αρχή της ενότητας (module) που περιέχει το υποπρόγραμμακαι χρησιμοποιεί το κύριο πρόγραμμα:

MODULE MODMIMPLICIT NONEREAL :: P, Q, ALCONTAINS

REAL FUNCTION AM(X) REAL :: X AM = P*0.5*X + Q*AL*0.5*X - Q*0.5*X**2 IF (X > AL/2.0) AM = AM - P*(X-AL*0.5)END FUNCTION AM

END MODULE MODM

PROGRAM KAM USE MODM IMPLICIT NONE READ (*, *) P, Q, AL WRITE (*, *) AM(0.0) WRITE (*, *) AM(AL*0.25) WRITE (*, *) AM(AL*0.5) WRITE (*, *) AM(AL*0.75) WRITE (*, *) AM(AL)END PROGRAM KAM

Οι μεταβλητές P, Q, AL είναι κοινές σε όλες τις συναρτήσεις που περιέχονται στη module. Επίσηςείναι κοινές και στο πρόγραμμα μέσω της εντολής USE, και πιο συγκεκριμένα η εντολή READ τουκυρίου προγράμματος θέτουν τιμές στις μεταβλητές P, Q, AL που έχουν δηλωθεί στη moduleMODM.

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 29

Page 30: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Δευτέρα 5/5/2014 10:45-14:30, B' πολ. Μηχανικών, Προγραμματισμός Η/Υ, θεωρία, Α Τμήμα (01AB) Άσκηση (παλιό θέμα)Δίνονται από το πληκτρολόγιο ο βαθμός εργασίας και ο βαθμός γραπτού ενός φοιτητή ως ακέραιοιαριθμοί. Να συντάξετε πρόγραμμα σε Fortran και το αντίστοιχο διάγραμμα ροής, το οποίο ναδιαβάζει τους βαθμούς κάθε φοιτητή και να υπολογίζει και να τυπώνει τον τελικό βαθμό κάθεφοιτητή που υπολογίζεται ως ο μέσος όρος (πραγματικός αριθμός) της εργασίας και του γραπτού μετις ακόλουθες εξαιρέσεις:i. Αν ο βαθμός του γραπτού είναι μηδέν τότε ο τελικός βαθμός είναι 0.ii. Αν ο βαθμός του γραπτού είναι μικρότερος από 3, τότε ο τελικός βαθμός είναι ο μέσος όρος αν ομέσος όρος είναι μικρότερος από 4, ή διαφορετικά 4.iii. Αν ο βαθμός της εργασίας είναι μικρότερος από 5, τότε ο τελικός βαθμός είναι ο μέσος όρος ανο μέσος όρος είναι μικρότερος από 4, ή διαφορετικά 4.Να τυπώνει και τον στρογγυλευμένο τελικό βαθμό κάθε φοιτητή, με στρογγύλευση στονπλησιέστερο ακέραιο.

(5 μονάδες)

ΑνάλυσηΗ συνάρτηση INT() κάνει πάντα αποκοπή δεκαδικών ψηφίων και έτσι η στρογγύλευση στονκοντινότερο ακέραιο γίνεται με το τέχνασμα Κ = INT(A+0.5):

INT(7.2+0.5) -> INT(7.7) -> 7 (η συνάρτηση INT() κάνει αποκοπή δεκαδικών)INT(7.5+0.5) -> INT(8.0) -> 7INT(7.8+0.5) -> INT(8.3) -> 8

Το τέχνασμα δεν λειτουργεί για αρνητικούς αριθμός και έτσι η Fortran έχει τη συνάρτηση NINT()που κάνει στρογγύλευση στον πλησιέστερο ακέραιο σε θετικούς και αρνητικούς αριθμούς:

NINT(7.2) -> 7NINT(7.5) -> 7NINT(7.8) -> 8NINT(-7.2) -> -7NINT(-7.5) -> -7NINT(-7.8) -> -8

Η συνάρτηση NINT, όπως και η INT(), επιστρέφει τον default ακέραιο που είναι 4 bytes. Αν πρέπεινα επιστρέψει ακέραιο άλλου είδους, η συνάρτηση συντάσσεται:

NINT(A, KIND)όπου KIND είναι το είδος του ακέραιου (πχ 8 για ακέραιο των 8 bytes).Παρόμοια με τη συνάρτηση NINT(A) είναι η συνάρτηση ANINT(A), η οποία επιστρέφει τονπλησιέστερο ακέραιο, αλλά μετατροπή στον τύπο της μεταβλητής A, δηλαδή αν η A είναιπραγματική επιστρέφει πραγματικό αριθμό:PROGRAM STROG REAL(4) :: A, AI A = 7.8 AI = ANINT(A) WRITE (*, *) AI, BI, ZIEND PROGRAM STROG

Κώδικας:

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 30

Page 31: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

program mat implicit none integer :: ierg, igra, itel real :: ave read (*, *) ierg, igra if (ierg == 0) then ave = 0.0 else if (igra < 3) then ave = real(ierg+igra)*0.5 if (ave .gt. 4.0) ave = 4.0 else if (ierg .lt. 5) then ave = real(ierg+igra)*0.5 if (ave .gt. 4.0) ave = 4.0 else ave = real(ierg+igra)*0.5 end if itel = nint(ave) write (*, *) ierg, igra, ave, itelend program mat

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 31

Page 32: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Δομές επανάληψης

1. Συνεχής επανάληψης

DO εντολέςEND DO

Οι εντολές μπορεί να είναι πολλές ή μία ή και καμία. Οι εντολές αυτές εκτελούνται η μία μετά τηνάλλη και μετά ξανά από την αρχή. Η διαδικασία αυτή λέγεται βρόχος. Ο βρόχος στην συγκεκριμένηπερίπτωση επαναλαμβάνεται επ' άπειρο.

2. Συνεχής επανάληψη με έξοδο όταν μία συνθήκη είναι αληθής

DO εντολές α IF (συνθήκη) EXIT εντολές βEND DOεντολές γ

Αν η συνθήκη είναι ψευδής εκτελούνται οι εντολές α και μετά οι εντολές β και μετά ξανά από τηναρχή. Αν σε κάποια επανάληψη ο συνθήκη γίνει αληθής, εκτελούνται οι εντολές α, οι εντολές β δενεκτελούνται, τερματίζεται ο βρόχος και στη συνέχεια εκτελούνται οι εντολές γ που είναι μετά τηνεντολή END DO.

3. Επανάληψη με έξοδο για όσο μία συνθήκη είναι αληθής

DO WHILE (συνθήκη) εντολές αEND DOεντολές β

Όσο η συνθήκη παραμένει αληθής, εκτελούνται οι εντολές α και μετά ξανά από την αρχή. Αν ησυνθήκη γίνει ψευδής σε κάποια επανάληψη, τότε ο βρόχος τερματίζεται και στη συνέχειαεκτελούνται οι εντολές β που είναι μετά την εντολή END DO. Αν η συνθήκη είναι αρχικά αληθής οιεντολές α δεν θα εκτελεστούν ούτε μία φορά.Μέσα στις εντολές α, μπορεί να υπάρχουν και μία η περισσότερες εντολές EXIT: IF (άλλησυνθήκη) EXITΑν κάποια από τις συνθήκες είναι αληθής, τερματίζεται στο σημείο αυτό ο βρόχος και στησυνέχεια εκτελούνται οι εντολές β που είναι μετά την εντολή END DO.

4. Επανάληψη με μετρητή

DO i=i1, i2, i3 εντολές αEND DOεντολές β

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 32

Page 33: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Η i είναι ακέραια μεταβλητή. Οι i1, i2, i3 είναι ακέραιες σταθερές, ακέραιες μεταβλητές, ήακέραιες αριθμητικές παραστάσεις. Αρχικά η μεταβλητή i παίρνει την τιμή i1. Στη συνέχειαεκτελούνται οι εντολές. Στη συνέχεια η μεταβλητή i αυξάνεται κατά i3 (i3 είναι το βήμα τηςεπανάληψης). Αν i>i2 τότε ο βρόχος τερματίζεται και στη συνέχεια εκτελούνται οι εντολές β πουείναι μετά την εντολή END DO. Αλλιώς εκτελούνται πάλι οι εντολές α και η διαδικασίαεπαναλαμβάνεται μέχρι i>i2. Αν αρχικά i>i2 (δηλαδή i1>i2) οι εντολές α δεν θα εκτελεστούν ούτεμία φορά.Η i3 μπορεί να παραληφθεί. Αν παραληφθεί τότε θεωρείται ότι i3=1.Μέσα στις εντολές α, μπορεί να υπάρχουν και μία η περισσότερες εντολές EXIT: IF (άλλησυνθήκη) EXITΑν κάποια από τις συνθήκες είναι αληθής, τερματίζεται στο σημείο αυτό ο βρόχος και στησυνέχεια εκτελούνται οι εντολές β που είναι μετά την εντολή END DO.

Παράδειγμα

DO I=0, 12, 3 WRITE (*, *) IEND DO (Στην αίθουσα αν γίνει πίνακας με τις τιμές που που παίρνει η μεταβλητή i).Στην οθόνη θα τυπωθεί:036912

ΠαράδειγμαDO I=100, 12, 3 WRITE (*, *) IEND DO Στην οθόνη δεν θα τυπωθεί τίποτα: οι εντολές του βρόχου δεν θα εκτελεστούν ούτε μία φορά.

Περιορισμοί της επανάληψης με μετρητή:α. Η μεταβλητή βρόχου δεν πρέπει να αλλάζει τιμή μέσα στο βρόχο είτε με ανάθεση είτε μεανάγνωση. Ως παράδειγμα ο παρακάτω κώδικας είναι λάθος.DO I=0, 12, 3 WRITE (*, *) I I = 20 !ΛΑΘΟΣ READ (*, *) I !ΛΑΘΟΣEND DO

β. Οι i1, i2, i3 δεν πρέπει να αλλάζουν τιμή μέσα στο βρόχο. Αν i1, i2, i3 είναι μεταβλητές, αυτές οιμεταβλητές δεν πρέπει να αλλάζουν τιμή εντός του βρόχου.

J = 0N = 12ISTEP = 3DO I=J, N, ISTEP WRITE (*, *) I

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 33

Page 34: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

J = 20 !ΛΑΘΟΣ N = N + 1 !ΛΑΘΟΣ READ (*, *) ISTEP !ΛΑΘΟΣEND DO

γ) Το βήμα i3 δεν πρέπει να είναι μηδέν.

δ) Μετά την εξάντληση του βρόχου η μεταβλητή βρόχου i δεν έχει συγκεκριμένη τιμή. Στο επόμενοπαράδειγμα η μεταβλητή k ΔΕΝ έχει την τιμή 11:DO K=1, 10, 1 WRITE (*, *) KEND DOJ = K**2 !ΛΑΘΟΣ, δεν γνωρίζουμε τι τιμή έχει η K

Αντιθέτως αν ο βρόχος διακοπεί με εντολή EXIT τότε η μεταβλητή i έχει την τιμή που είχε ότανδιακόπηκε ο βρόχος:DO K=1, 10, 1 WRITE (*, *) K IF (K > 6) EXITEND DOJ = K**2 !η K έχει τιμή 7, και γνωρίζουμε ότι ο βρόχος δεν θα εξαντληθεί

Το επόμενο παράδειγμα είναι επίσης λάθος:READ (*, *) NDO K=1, N, 1 WRITE (*, *) K IF (K > 6) EXITEND DOJ = K**2 !ΛΑΘΟΣ, δεν γνωρίζουμε αν ο βρόχος διακοπεί (Ν>=7), ή θαεξαντληθεί (Ν<7)

Αν θέλουμε την τελευταία τιμή του βρόχου, την αποθηκεύουμε σε άλλη μεταβλητή:READ (*, *) NDO K=1, N, 1 L = K WRITE (*, *) K IF (K > 6) EXITEND DOJ = L**2 !ΣΩΣΤΟ, η μεταβλητή L δεν είναι ο μετρητής του βρόχου και έχειτιμή

5. Επανάληψη με μετρητή σε παλαιότερες εκδόσεις της FortranΗ δομή επανάληψης DO με μετρητή συντάσσεται και με label (ετικέτας) που είναι ένας ακέραιοςμεταξύ 1 και 999999 και της CONTINUE (FORTRAN77 και παλιότερες εκδόσεις):DO 100 I=I1, I2, I3 ή DO 100 I=I1, I2, I3 εντολή1 εντολή1 .... .... εντολήΝ 100 εντολήΝ100 CONTINUE

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 34

Page 35: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Άσκηση Να υπολογιστεί το άθροισμα 1n + 2n + 3n + 4n + .... όπου το n δίνεται από το χρήστη για 30 όρους.PROGRAM S implicit none integer :: isum, n, i ISUM = 0 READ (*, *) N DO I=1, 30 ISUM = ISUM + I**N END DO WRITE (*, *) ISUMEND program s

ΆσκησηΝα υπολογιστεί το υπολογιστεί ο ελάχιστος και μέγιστος βαθμός. Στην αρχή δίνεται το πλήθος τωνβαθμών και μετά ένας ένας οι βαθμοί ως πραγματικοί αριθμοί που πρέπει να στρογγυλευθούν στοπλησιέστερο ακέραιο πολλαπλάσιο του 0.5.

ΑνάλυσηΗ συνάρτηση INT(X) μετατρέπει πραγματικό σε ακέραιο με αποκοπή δεκαδικών. Για να γίνειστρογγύλευση χρησιμοποιούμε το τέχνασμα: K=INT(X+0.5)Εναλλακτικά χρησιμοποιούμε τη συνάρτηση NINT(X) που στρογγυλεύει στον πλησιέστερο.Για να στρογγυλεύσουμε σε ακέραιο πολλαπλάσιο του D (π.χ. στην άσκηση D=0.5) βρίσκουμεπόσα D έχει το X, και μετά στρογγυλεύουμε στον πλησιέστερο ακέραιο: K = NINT(X/D) X = REAL(K) * DΗ συνάρτηση REAL(K) μετατρέπει έναν ακέραιο σε πραγματικό.

Για την εύρεση του ελάχιστου θεωρούμε ότι ο ελάχιστος bmin είναι ο πρώτος βαθμός πουδιαβάζεται. Αν όταν διαβαστεί ο δεύτερος βαθμός αποδειχθεί ότι είναι μικρότερος από το bmin,κάναμε λάθος στην υπόθεσή μας και το διορθώνουμε: βάζουμε το δεύτερο βαθμό στο bmin. Για τηνεύρεση του μέγιστου θεωρούμε ότι ο ελάχιστος bmax είναι ο πρώτος βαθμός που διαβάζεται (ναδείξετε ότι μπορεί ο πρώτος να είναι και ο μέγιστος και ο ελάχιστος ταυτόχρονα). Αν ότανδιαβαστεί ο δεύτερος βαθμός αποδειχθεί ότι είναι μεγαλύτερος από το bmax, κάναμε λάθος στηνυπόθεσή μας και το διορθώνουμε: βάζουμε το δεύτερο βαθμό στο bmax. Ομοίως για όλους τουςεπόμενους βαθμούς.

PROGRAM mm implicit none integer :: i, n, k real :: b, bmin, bmax, a READ (*, *) N DO I=1, N READ (*, *) B A = B / 0.5 K = NINT(A) B = FLOAT(K)*0.5 IF (I == 1) THEN BMIN = B

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 35

Page 36: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

BMAX = B else IF (B < BMIN) BMIN = B IF (B > BMAX) BMAX = B END IF END DO WRITE (*, *) BMIN, BMAXend program mm

Ατέρμονας βρόχοςΑν δεν είναι γνωστός ο αριθμός επαναλήψεων εκ των προτέρων, μπορούμε να εκτελέσουμε έναβρόχο που δεν τερματίζεται (από μόνος του), και να τον τερματίζουμε “χειρωνακτικά” αν μίασυνθήκη γίνει αληθής: DO εντολές IF (συνθήκη) exit εντολές END DOΟι εντολές μεταξύ του DO και END DO εκτελούνται από πάνω προς τα κάτω, και στη συνέχειαξαναεκτελούνται δεύτερη φορά, τρίτη φορά έως το άπειρο. Ο βρόχος αυτός λέγεται ατέρμονας γιατίδεν τερματίζεται. Μία ή περισσότερες εντολές του βρόχου πρέπει να περιέχει την εντολή EXIT, ηοποία τερματίζει το βρόχο, και συνεχίζει τη ροή του προγράμματος μετά το END DO.

Παράδειγμα Να υπολογιστεί ο μέσος όρος και ο ελάχιστη αντοχή εδαφικών δοκιμίων δοκιμίων η οποίαμετρείται σε (ακέραιο) αριθμό πρότυπων κτύπων. Οι ακέραιοι αριθμοί δίνονται από το χρήστη.Στο τέλος ο χρήστης δίνει ένα ειδικό νούμερο (sentinel – φρουρός), στην περίπτωσή μας ένααρνητικό νούμερο για να δηλώσει το τέλος των δεδομένων. Ας σημειωθεί ότι το ειδικό νούμερο δενμπορεί να είναι έγκυρος αριθμός κτύπων (1-50) γιατί αλλιώς μπορεί να σταματήσουμε ναδιαβάζουμε δεδομένα νωρίτερα από ότι πρέπει. Επίσης το ειδικό νούμερο δεν θα ληφθεί υπόψη στομέσο όρο, ούτε και για την εύρεση του ελάχιστου (αφού δεν είναι έγκυρος αριθμός κτύπων).

PROGRAM AVERAG implicit none integer :: i, ib, ibmin real :: av AV = 0.0 IBMIN = 100 i = 0 DO read (*, *) IB IF (ib < 0) exit i = i + 1 if (i > 100) stop 'Πάρα πολλά δοκίμια' if (IB < IBMIN) IBMIN = IB AV = AV + FLOAT(IB) END DO AV = AV / FLOAT(I) WRITE (*, *) IBMIN, INT(AV+0.5)end program averag

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 36

Page 37: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Για την εύρεση του ελάχιστου εδώ ακολουθούμε άλλη μεθοδολογία. Έστω ότι ο ελάχιστος αριθμόςκτύπων ibmin είναι ένα πολύ μεγάλο νούμερο, το οποίο είναι μεγαλύτερο από όλους τους δυνατούςαριθμούς κτύπων. Συγκρίνουμε το ibmin με τον πρώτο αριθμό κτύπων που διαβάζουμε ib. Ο ib θαείναι σίγουρα μικρότερος και τοποθετούμε αυτόν στο ibmin. Στην συνέχεια ελέγχουμε όλους τουςεπόμενους βαθμούς όπως και στο προηγούμενο πρόγραμμα.Η συνθήκη i>100 είναι το αντίστοιχο του συντελεστή ασφαλείας για τον προγραμματισμό. Ανξεπεράσουμε τα 100 δοκίμια κάτι δεν πάει καλά.

Δομημένος προγραμματισμόςΕίναι αυτός κατά τον οποίο το πρόγραμμα αποτελείται από τμήματα τα οποία:α. Εκτελούνται εν γένει από πάνω προς τα κάτω.β. Αν το πρόγραμμα φτάσει στην αρχή του τμήματος τότε εγγυημένα θα φτάσει και στο τέλος τουτμήματος (εξαιρείται από αυτό τον κανόνα η εντολή STOP που τερματίζει το πρόγραμμα, και ηεντολή RETURN που τερματίζει ένα υποπρόγραμμα).Ο βρόχος DO είναι ένα τέτοιο τμήμα γιατί οι εντολές μέσα στο βρόχο εκτελούνται από πάνω προςτα κάτω, και επίσης είναι σίγουρο ότι σε κάποια φάση ο βρόχος θα τελειώσει και θα εκτελεστούν οισειρές μετά από το βρόχο. Το υποπρόγραμμα τύπου συνάρτησης (FUNCTION) είναι άλλο ένατέτοιο τμήμα.Ο δομημένος προγραμματισμός συνιστάται γιατί με αυτόν η ροή ενός προγράμματος είναιξεκάθαρη με την πρώτη ματιά.

Εντολές μεταφοράςΣε σπάνιες περιπτώσεις είναι χρήσιμο να διακοπεί η ροή του προγράμματος (από πάνω προς τακάτω) και να συνεχιστεί σε κάποιο απομακρυσμένο σημείο του κώδικα, όπως για παράδειγμα σεπερίπτωση καταστροφικού λάθους.Κάθε εντολή της Fortran μπορεί να έχει αριστερά της έναν αριθμό 1 έως 99999 ο οποίος λέγεταιετικέτα (label) της εντολής. Πχ:120 WRITE(*, *) AΗ εντολής μεταφοράς στη Fortran συντάσσεται: GO TO ετικέταόπου η ετικέτα είναι η ετικέτα κάποιας εντολής (ακέραιος αριθμός μεταξύ 1 και 99999). Γιαπαράδειγμα: A=3.14 K=8 GO TO 569 B=1.0 C=2.0569 WRITE (*, *) A

Οι εντολές B=1.0 και C=2.0 δεν θα εκτελεστούν ποτέ (και είναι στην πραγματικότητα λάθοςπρογράμματος εδώ).Η ασυλλόγιστη χρήση της εντολής GO TO μπορεί πολύ εύκολα να οδηγήσει σε ακατανόηταπρογράμματα όπου η ροή του προγράμματος είναι τόσο μπερδεμένη όσο μπερδεμένα είναι και ταμακαρόνια σε μία χύτρα. Αυτός ο προγραμματισμός ονομάζεται διεθνώς προγραμματισμόςσπαγέτου (spagetti programmming).Η χρήση της εντολής GO TO πρέπει να είναι φειδωλή και να χρησιμοποιείται έτσι ώστε οδηγεί σεδομημένο προγραμματισμό.

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 37

Page 38: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

ΠαράδειγμαΝα γίνει το προηγούμενο πρόγραμμα με GO TO (δεν συνιστάται, γίνεται μόνο για διδακτικούςλόγους επειδή πολλά προγράμματα Fortran το έχουν - δεν πρέπει να χρησιμοποιείται σε νέαπρογράμματα) υπολογιστεί ο μέσος όρος βαθμολογίας (ακέραιοι αριθμοί) που δίνεται από τοχρήστη. Στο τέλος ο χρήστης δίνει ένα αρνητικό νούμερο για να δηλώσει το τέλος των δεδομένων.Εδώ δίνουμε το πρόγραμμα με GO TO και χωρίς έλεγχο:

PROGRAM AVERAG implicit none integer :: i, ib, ibmin real :: av AV = 0.0 IBMIN = 100 i = 0100 continue read (*, *) IB IF (ib < 0) go to 110 i = i + 1 if (i > 100) stop 'Πάρα πολλά δοκίμια' if (IB < IBMIN) IBMIN = IB AV = AV + FLOAT(IB) go to 100110 continue AV = AV / FLOAT(I) WRITE (*, *) IBMIN, INT(AV+0.5)end program averag

Η εντολή CONTINUE δεν κάνει απολύτως τίποτα. Είτε τη βάλουμε είτε οι έχει το ίδιο αποτέλεσμακαι υπάρχει για να παίρνει απλά μια ετικέτα.Οι εντολές CONTINUE (οι οποίες δεν κάνουν τίποτα) έχουν ως σκοπό να δυσχεραίνουν το χρήσητου GOTO έτσι ώστε να μην γίνεται ασυλλόγιστη χρήση του. Επίσης έχουν το πλεονέκτημα ότιανάμεσα στα δύο CONTINUE περικλείεται ο βρόχος. Παρά τη χρήση του GO TO, το παραπάνωπρόγραμμα τηρεί τις αρχές του δομημένου προγραμματισμού, αφού εν γένει η ροή τουπρογράμματος είναι από πάνω προς τα κάτω, και αν η ροή του προγράμματος περάσει από τοπρώτο CONTINUE (την αρχή του βρόχου) είναι εγγυημένο ότι θα περάσει και από το δεύτεροCONTINUE (το τέλος του βρόχου), (με εξαίρεση αν τερματιστεί το πρόγραμμα ή τουποπρόγραμμα).

Εντολή με τη συνθήκη τερματισμού στην αρχή.Αν γνωρίζουμε τη συνθήκη τερματισμού από την αρχή αλλά η συνθήκη δεν περιλαμβάνειακεραίους αριθμούς μπορούμε να χρησιμοποιήσουμε την εντολή: DO WHILE (συνθήκη) εντολές END DO

Ο βρόχος θα συνεχίζει να εκτελείται όσο η συνθήκη παραμένει αληθής.

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 38

Page 39: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Παράδειγμα. Να υπολογιστεί η σειρά 02 + 0.152 + 0.302 + 0.452 + ... + 60.02

Επειδή δεν μπορούν να χρησιμοποιηθούν πραγματικές μεταβλητές και σταθερές στην εντολή DOχρησιμοποιούμε DO WHILE:

PROGRAM SEIRA implicit none real :: sum, oros SUM = 0.0 OROS = 0.0 do while (oros <= 60.0) SUM = SUM + OROS**2 OROS = OROS + 0.15 end do write (*, *) SUMend program seira

Παρατηρούμε ότι η εκτέλεση των εντολών στο βρόχο είναι από πάνω προς τα κάτω, και όταντελειώνει ο βρόχος η ροή του προγράμματος συνεχίζει αμέσως από κάτω από το βρόχο. Συνεπώς οπρογραμματισμός είναι δομημένος.Αν τρέξουμε το πρόγραμμα θα διαπιστώσουμε ότι δεν έχει προσθέσει τον αριθμό 60. Αυτό γίνεταιγιατί με 6 σημαντικά ψηφία, η μεταβλητή OROS έχει 4 δεκαδικά ακρίβεια όταν γίνει > 50. Έτσιαντί η OROS να φτάσει στο 59.85 όπως έπρεπε, λόγων των αριθμητικών λαθών αποκοπής φτάνειστο 59.8502. Προσθέτοντας 0.15 γίνεται 60.0002 που είναι μεγαλύτερο από το 60.0, και ο βρόχοςσταματάει χωρίς να προσθέσει το 60.0. Σε αυτές τις περιπτώσεις πρέπει να δώσουμε μια ανοχή πουμπορεί να είναι το μισό βήμα:PROGRAM SEIRA implicit none real :: sum, oros SUM = 0.0 OROS = 0.0 do while (oros <= 60.075) SUM = SUM + OROS**2 OROS = OROS + 0.15 end do write (*, *) SUM end program seira

Παράδειγμα Η κυβική ρίζα ενός αριθμού a υπολογίζεται από το αναδρομικό τύπο

fn = 2fn-1/3 + a/(3fn-12) όπου f0=a/3.

Κάθε διαδοχική προσέγγιση είναι καλύτερη από την προηγούμενη. Να συνταχθεί πρόγραμμα πουνα υπολογίζει την κυβική ρίζα με ακρίβεια 4 δεκαδικών ψηφίων ή 10-4. Αν χρειαστούν πάνω από100 διαδοχικές προσεγγίσεις να εμφανίζεται μήνυμα λάθους. Να γίνει διερεύνηση για ειδικέςπεριπτώσεις (αρνητικοί αριθμοί, μηδέν, θετικοί αριθμοί).

ΑνάλυσηΗ κυβική ρίζα του 14 είναι 2.410142. Οι διαδοχικές προσεγγίσεις με τον αναδρομικό τύπο είναι:

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 39

Page 40: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

4.66666651 3.32539654 2.63893843 2.42940569 2.41029453 2.41014242 2.41014218 Παρατηρούμε ότι στη 4η προσέγγιση, το πρώτο δεκαδικό (το 4) είναι σωστό. Στην πέμπτηπροσέγγιση το πρώτο δεκαδικό παραμένει 4 και παραμένει 4 σε όλες τις επόμενες διαδοχικέςπροσεγγίσεις. Αυτό δεν είναι σύμπτωση. Αν υποθέσουμε ότι στην πέμπτη προσέγγιση το πρώτοδεκαδικό γινόταν 5, τότε η πέμπτη προσέγγιση θα ήταν χειρότερη από την τέταρτη. Αυτό είναιάτοπο διότι αποδεικνύεται μαθηματικά η σύγκλιση της ακολουθίας. Έτσι από τη στιγμή που θαβρεθεί το πρώτο δεκαδικό ψηφίο όλες οι επόμενες διαδοχικές προσεγγίσεις θα έχουν το ίδιο πρώτοδεκαδικό ψηφίο. Συνεπώς αν θέλουμε ακρίβεια ενός δεκαδικού, αρκεί δύο διαδοχικές προσεγγίσειςνα έχουν το ίδιο πρώτο δεκαδικό ψηφίο, ή η απόλυτη διαφορά τους να είναι μικρότερη από 0.1. Για4 δεκαδικά ψηφία το κριτήριο είναι:

| fn-fn-1| < 10-4

Κώδικας:

program kyb real :: a, akyb, fp integer :: i READ (*, *) A IF (A == 0.0) THEN akyb = 0.0 else FP = A/3.0 i = 0 DO akyb = 2.0*FP/3.0 + A/(3.0*FP**2) IF (ABS(akyb-FP) < 1.0E-4) exit i = i + 1 if (i > 100) STOP 'Πάρα πολλές διαδοχικές προσεγγίσεις' fp = akyb END DO end if WRITE (*, *) akybend program kyb

Κώδικας χρησιμοποιώντας υποπρογράμματα τύπου συνάρτησης:

module modkybimplicit nonecontains

real function akyb(a) real :: a real :: fp integer :: i akyb = 0.0

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 40

Page 41: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

IF (A == 0.0) return FP = A/3.0 DO i=1, 100 akyb = 2.0*FP/3.0 + A/(3.0*FP**2) IF (ABS(akyb-FP) < 1.0E-4) return FP = akyb END DO STOP 'Πάρα πολλές διαδοχικές προσεγγίσεις'end function akyb

end module modkyb

PROGRAM KYB use modkyb implicit none real :: a READ (*, *) A WRITE (*, *) akyb(a)end program kyb

Η εντολή STOP μέσα στη συνάρτηση επιτρέπεται και σταματάει τελείως την εκτέλεση τουπρογράμματος, συνήθως μετά από ένα σημαντικό λάθος που αντιλαμβάνεται το πρόγραμμα. Ηεντολή RETURN, η οποία δεν είναι στο τέλος του κώδικα της συνάρτησης, τερματίζει τηνεκτέλεση της συνάρτησης και επιστρέφει την τιμή (akyb) που υπολόγισε στο κύριο πρόγραμμα. Ηροή του προγράμματος συνεχίζεται στο κύριο πρόγραμμα, αμέσως μετά από τη κλήση τηςσυνάρτησης. Μπορούν να χρησιμοποιηθούν πολλές εντολές STOP και RETURN σε μίασυνάρτηση, κατά το δοκούν.

ΆσκησηΝα βρεθεί η λύση της εξίσωσης

f(x) = exp(x)-10sin(x) = 0για 0<=x<=4, με ακρίβεια 3 δεκαδικά (της λύσης x, όχι της f(x)). Αρχικά να μη χρησιμοποιηθείblock if.

Θα χρησιμοποιήσουμε εξαντλητική έρευνα (exhaustive search). Δηλαδή θα δοκιμάσουμε όλουςτους δυνατούς αριθμούς x και θα βρούμε ποιος από αυτούς δίνει f(x)=0. Επειδή θέλουμε ακρίβεια 3δεκαδικά, ή 0.001, θα δοκιμάσουμε

x=0, 0.001, 0.002, 0.003, ... 0.998, 0.999, 1, 1.001, 1.002, ..., 3.999, 4Επίσης αν η λύση έχει περισσότερα από 3 δεκαδικά (όπως στην περίπτωσή μας), αυτό σημαίνει ότιο αριθμός x που θα βρούμε θα είναι προσεγγιστικός και δεν θα δίνει f(x) ακριβώς ίσο με μηδέν. Θαδίνει f(x) κοντά στο μηδέν. Άρα πρέπει να βρούμε ποιος αριθμός δίνει το ελάχιστο f(x) κατάαπόλυτη τιμή.Έστω ότι η λύση είναι ο αριθμός xr=0.0. Αυτός δίνει τιμή στη συνάρτηση fr = |f(x)|Δοκιμάζουμε έναν άλλον αριθμό xp=.001. Αν fp=|f(xp)| > fr τότε σωστά υποθέσαμε ότι η λύσηείναι ο αριθμός xr. Αν fp<fr τότε κάναμε λάθος και θέτουμε

xr=xr, fr=fpοπότε πάλι η μεταβλητή xr έχει τη λύση.

Έτσι το διάγραμμα ροής είναι:

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 41

Page 42: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 42

Page 43: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Ο κώδικας είναι:

PROGRAM riza implicit none real :: xr, fr, xp, fp XR = 0.0 FR = ABS(EXP(XR)-10.0*SIN(XR)) XP = 0.0 do XP = XP + 0.001 IF (XP > 4.0005) exit FP = ABS(EXP(XP)-10.0*SIN(XP)) IF (FP < FR) FR=FP , XR=XP end do WRITE (*, *) 'Η ΛΥΣΗ ΕΙΝΑΙ Χ=', XR, ' ΔΙΝΕΙ F(X)=', FRend program riza

Δυστυχώς δεν μπορούμε να βάλουμε 2 εντολές μετά από IF (είναι κοινό λάθος). Η FORTRAN77(και η Fortran95-2008) διαθέτει και μία σύνταξη IF που επιτρέπει πολλές εντολές υπό συνθήκη:

IF (συνθήκη) THEN (πολλές) εντολές ΑEND IFεντολές Β

Έτσι το πρόγραμμα γίνεται:

PROGRAM riza implicit none real :: xr, fr, xp, fp XR = 0.0 FR = ABS(EXP(XR)-10.0*SIN(XR)) XP = 0.0 do XP = XP + 0.001 IF (XP > 4.0005) exit FP = ABS(EXP(XP)-10.0*SIN(XP)) IF (FP < FR) then FR = FP XR = XP end if end do WRITE (*, *) 'Η ΛΥΣΗ ΕΙΝΑΙ Χ=', XR, ' ΔΙΝΕΙ F(X)=', FRend program riza

Η λύση που βρίσκει το πρόγραμμα είναι: x=0.112 με f(x)=0.0008

Άσκηση για το σπίτι:α) Τρέξτε το πρόγραμμα για 2<=x<=4. Τι παρατηρείτε; (Βρέθηκε άλλη λύση x=2.134. η οποία είναιμεταξύ 0 και 4. Γιατί δεν τη βρήκε την πρώτη φορά; έτυχε για x=0.112 να δίνει f(x)=0.0008 ενώ γιαx=2.134 να δίνει f(x)=0.0068).

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 43

Page 44: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

β) Τρέξτε το πρόγραμμα για 3<=x<=5. Τι παρατηρείτε; (βρίσκει “λύση” x=3.000 με f(x)=18.674 ηοποία βέβαια δεν είναι λύση. Έχει βρει στην ουσία το ελάχιστο της συνάρτησης για 3<=x<=5).γ) Κάνετε το διάγραμμα της συνάρτησης για 0<=x<=5 υπολογίζοντας τιμές της f(x) ανά 0.001(5001 γραμμές), για να επιβεβαιώσετε γραφικά τις δύο λύσεις.

Εμφωλευμένα DO.Το εσωτερικό DO πρέπει να περικλείεται μέσα στο εξωτερικό, όπως ακριβώς και στα εμφωλευμέναblock if.

ΠαράδειγμαΝα υπολογιστεί η σειρά για N που δίνεται από το χρήστη:1/1! + 1/2! + 1/3! + .. + 1/N!

program seira implicit none integer :: n, k, j, i real :: a, s read (*, *) n S = 0.0 DO I=1, N K = 1 DO J=1, I K = K*J END DO S = S + 1.0/real(K) END DO WRITE (*, *) Send program seira

Για μεγαλύτερη αναγνωσιμότητα:

module modparimplicit nonecontains

integer function ipar(i) integer :: i integer :: j ipar = 1 do j=1, i ipar = ipar * j end doend function ipar

end module modpar

program seira use modpar implicit none integer :: n, i

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 44

Page 45: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

real :: a, s read (*, *) n S = 0.0 DO I=1, N S = S + 1.0/real(ipar(i)) END DO WRITE (*, *) Send program seira

Βέβαια στην πράξη δεν χρειάζεται να υπολογίζεται το i! από την αρχή κάθε φορά. Μπορούμε ναχρησιμοποιήσουμε το αναδρομικό τύπο:

i! = (i-1)! ∙ iΤο (i-1)! έχει υπολογιστεί από τον προηγούμενο όρο της σειράς. Έτσι ο κώδικας γίνεται:

program seira implicit none integer :: n, i, ipar real :: a, s read (*, *) n S = 0.0 ipar = 1 DO I=1, N ipar = ipar * I S = S + 1.0/real(ipar) END DO WRITE (*, *) Send program seira

ΠαράδειγμαΝα συντάξετε πρόγραμμα που μετρά και να τυπώνει την ώρα κάθε δευτερόλεπτο μίας μέρας μεμορφή:

ωω:μμ:λλ π.χ. 0:45:12 ή 18: 7:55

PROGRAM ROL implicit none integer :: n1, ior, ilept, ideyt, i, k N1 = 350000000 DO IOR=0, 23 DO ILEPT=0, 59 DO IDEYT=0, 59 WRITE (*, *) IOR, ILEPT, IDEYT DO I=1, N1 K = I**2 END DO END DO END DO END DOEND program rol

Η μεταβλητή N1 περιέχει ένα μεγάλο νούμερο που στον εσωτερικό βρόχο προκαλεί καθυστέρηση 1sec. Το νούμερο βρίσκεται για κάθε υπολογιστή με δοκιμή και λάθος.

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 45

Page 46: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Δευτέρα 12/5/2014 10:45-14:30, B' πολ. Μηχανικών, Προγραμματισμός Η/Υ, θεωρία, Α Τμήμα (01AB)

ΆσκησηΕύκαμπτος αγωγός αποχέτευσης έχει διάμετρο 11 εκατοστών και τυλίγεται σε κύλινδρο διαμέτρου1.0m και πλάτους 1.5m. Τι διάμετρο πρέπει πρέπει να έχουν οι πλευρικοί δίσκοι (καπάκια) τουκυλίνδρου για ασφαλή μεταφορά αγωγού μήκους 200m.

ΑνάλυσηΑς φανταστούμε ότι φτιάχνουμε δακτύλιους (δαχτυλίδια, κουλούρες) από τον αγωγό αποχέτευσηςμε διάμετρο Da ίση με τη διάμετρο κυλίνδρου Dk=1.0m για να χωρούν ακριβώς στον κύλινδρο. Τοπάχος Pa κάθε δακτυλίου είναι όσο η διάμετρος του αγωγού δηλαδή Pa=0.11 m. Το πλήθος τωνδακτυλίων που χωρούν σε κύλινδρο πλάτους Bk=1.5m είναι Na = Bk / Pa.Το μήκος κάθε δακτυλίους είναι La = π Da (περίμετρος κύκλου). Το μήκος όλων των δακτυλίωνείναι L1 = Na π Da.Ο κύλινδρος έχει τώρα καλυφθεί από μία στρώση με δακτυλίους. Για να βάλουμε από πάνω μίαδεύτερη στρώση από δακτυλίους, πρέπει οι νέοι δακτύλιοι να έχουν διάμετρο Da,2 = Dk + 2Pa.Πάλι χωρούν Na δακτύλιοι οι οποίοι θα έχουν συνολικό μήκος L2 = Na π Da,2.Γενικώς η διάμετρος της iοστής στρώσης είναι Da,i = Dk + (i-1) 2 Pa και το μήκος των δακτυλίωντης iοστής στρώσης Li = Na π Da,2.Σταματάμε να βάζουμε στρώσεις από δακτυλίους, όταν το συνολικό μήκος των στρώσεων Σliξεπεράσει το μκος του αγωγού Lmax=200m.Τότε η διάμετρος των πλευρικών δίσκων πρέπει να είναι όση είναι η διάμετρος της τελευταίαςστρώσης δακτυλίων + 2Pa για ασφάλεια.

program ag implicit none real :: Pa, Dk, Bk, pi, SL, AL, Da integer :: Nk, i Pa = 0.11 Dk = 1.0 Bk = 1.5 Nk = int(Bk/Pa) !Αριθμός βρόχων στο πλάτος του κυλίνδρου i = 0 pi = 3.14159 SL = 0.0 do i = i + 1 Da = Dk + real(i-1)*2.0*Pa !Πάνω Pa και κάτω Pa AL = real(Na) * pi * Da SL = SL + AL write (*, *) Da, SL if (SL > 200.0) exit end do write (*, *) Da+Paend program ag

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 46

Page 47: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Άσκηση (Παλαιό θέμα)Σε πολλαπλά σημεία ελαστικού σώματος έχουν γίνει μετρήσεις παραμορφώσεων εx, εy, γxy . Γιακάθε τριάδα εx, εy, γxy η κύρια ορθή τάση υπολογίζεται:

σ1=σ x+σ y

2+√( σ x−σ y2 )

2

+ τ xy2 όπου:

σ x=E

1−v2(ε x+vε y) , σ y=

E

1−v2(ε y+vεx ) , τ xy=

E2(1+v )

γ xy

Το μέτρο ελαστικότητας είναι E=30∙109 και ο λόγος Poisson v=0.1Οι τριάδες δίνονται από το πληκτρολόγιο η μία μετά την άλλη. Στο τέλος δίνεται τριάδα μηδενικών.Να συνταχθεί πρόγραμμα σε Fortran το οποίο να υπολογίζει και να τυπώνει στην οθόνη τη μέγιστηκύρια ορθή τάση (από όλες τις τριάδες).

(2.5 μονάδες)

PROGRAM THEMA1 implicit none real :: e, v, s1max, ex, ey, gxy, sx, sy, txy, s1 E = 30.0E9 V = 0.1 S1MAX = -1.0E30 DO READ (*, *) EX, EY, GXY IF (EX == 0.0) THEN IF (EY == 0.0) THEN IF (GXY == 0.0) EXIT END IF END IF SX = E/(1.0-V**2) * (EX + V*EY) SY = E/(1.0-V**2) * (EY + V*EX) TXY = E/(2.0*(1.0+V)) * GXY S1 = (SX+SY)/2.0 + SQRT(((SX-SY)/2.0)**2 + TXY**2) IF (S1 > S1MAX) S1MAX = S1 END DO WRITE (*, *) S1MAXEND program thema1

Η συνθήκη τερματισμού μπορεί να γραφεί καλύτερα ως: IF (EX.EQ.0.0 .AND. EY.EQ.0.0 .AND. GXY.EQ.0.0) EXIT

Άσκηση (Παλαιό θέμα)Η αποστάσεις x1(t) και x2(t) που διανύουν δύο οχήματα δίνονται από:x1( t )=6t 2

(1+0 .001 t ) και x2( t )=3t2(1+0 .001 t )+30 t

Όπου x είναι η απόσταση σε m και t≥0 είναι ο χρόνος σε sec. Να συνταχθεί πρόγραμμα σεFortran που να υπολογίζει και να τυπώνει στην οθόνη:α. Ποιο από τα δύο οχήματα (1 ή 2) θα διανύσει πρώτο απόσταση 500m και σε πόσο χρόνο.β. Ποιο από τα δύο οχήματα (1 ή 2) θα διανύσει πρώτο απόσταση 1000m και σε πόσο χρόνο.γ. Σε πόσο χρόνο (t>0) και σε ποια απόσταση θα ξεπεράσει το 1ο όχημα το 2ο (ή το 2ο θαξεπεράσει το 1ο).

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 47

Page 48: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Για να λύσετε το θέμα μπορείτε να υπολογίζετε την απόσταση ανά Δt=0.01sec ή λιγότερο. (3.5 μονάδες)

PROGRAM THEMA2 implicit none real :: t, x1, x2, dmax integer :: i DO I=1, 2 IF (I == 1) DMAX = 500.0 IF (I == 2) DMAX = 1000.0 T = 0.0 DO T = T + 0.01 X1 = 6.0*T**2*(1.0+0.001*T) X2 = 3.0*T**2*(1.0+0.001*T) + 30.0*T IF (X1 >= DMAX) THEN WRITE (*, *) DMAX, 1, T EXIT ELSE IF (X2 >= DMAX) THEN WRITE (*, *) DMAX, 2, T EXIT END IF END DO END DO

T = 0.01 X1 = 6.0*T**2*(1.0+0.001*T) X2 = 3.0*T**2*(1.0+0.001*T) + 30.0*T IF (X1 > X2) THEN DO T = T + 0.01 X1 = 6.0*T**2*(1.0+0.001*T) X2 = 3.0*T**2*(1.0+0.001*T) + 30.0*T IF (X2 >= X1) exit END DO ELSE DO T = T + 0.01 X1 = 6.0*T**2*(1.0+0.001*T) X2 = 3.0*T**2*(1.0+0.001*T) + 30.0*T IF (X1 >= X2) exit END DO END IF WRITE (*, *) X2, TEND program thema2

Χρησιμοποιώντας συναρτήσεις το ίδιο πρόγραμμα γίνεται πιο κατανοητό:

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 48

Page 49: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

module modaytokimplicit nonecontains

real function a1(t) real :: t a1 = 6.0*T**2*(1.0+0.001*T)end function a1

real function a2(t) real :: t a2 = 3.0*T**2*(1.0+0.001*T) + 30.0*Tend function a2

integer function idis(dmax) real :: dmax real :: t T = 0.0 DO T = T + 0.01 IF (a1(t) >= DMAX) THEN WRITE (*, *) DMAX, 1, T EXIT ELSE IF (a2(t) >= DMAX) THEN WRITE (*, *) DMAX, 2, T EXIT END IF END DO idis = 0end function idis

end module modaytok

PROGRAM THEMA2 use modaytok implicit none real :: t, x1, x2 integer :: itemp itemp = idis(500.0) itemp = idis(1000.0)

T = 0.01 X1 = a1(t) X2 = a2(t) DO T = T + 0.01 IF (X1 > X2) then if (a2(t) >= a1(t)) exit else

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 49

Page 50: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

if (a1(t) >= a2(t)) exit end if END DO WRITE (*, *) a1(t), a2(t), T ! x1 περίπου ίσο με x2END program thema2

(Εξήγηση της επίλυσης στην αίθουσα)

FORMAT (κεφ. 6, 11 από το βιβλίο)Φορμά Iw, Fw.d, nX, AwΈνα προς ένα αντιστοιχία μεταξύ μεταβλητών και φορμά. Ένα προς ένα αντιστοιχία μεταξύ writeκαι σειρών που γράφονται (αναλόγως και με το read).Μιγαδικοί αριθμοί με δύο φορμά Fw.dΕπανάληψη φορμά: nIw, nFw.d, nAw (από τις επαναλήψεις μόνο αυτή μπορεί να χρησιμοποιηθείκαι να είναι ο κώδικας κατανοητός).Παραδείγματα

Το φορμά F στο read να έχει πάντα μηδέν δεκαδικά ψηφία (πχ. F8.0).Επανάληψη πολλών φορμά με παρενθέσεις: n(Fw.d, Iw) (δεν συνιστάται).Επανάληψη FORMAT από την κοντινότερη αριστερή παρένθεση (δεν συνιστάται).Φορμά / (δεν συνιστάται).Φορμά BZ (δεν συνιστάται).Πάρα πολλά παραδείγματα.

ΠαράδειγμαΦτιάξτε πίνακα με ημίτονα και συνημίτονα ανά 0.1 μοίρες και ακρίβεια 8 δεκαδικά.

Επειδή η απλή ακρίβεια πραγματικών αριθμών έχουν μόνο 5 ή 6 σημαντικά ψηφία, θαχρησιμοποιηθεί διπλή ακρίβεια.

PROGRAM PIN implicit none integer :: i real(8) :: F, FRAD, C, S real(8), parameter :: PI=3.14159265358979323_8 do i=0, 900 f = real(i, 8) / 10.0_8 FRAD = F * PI / 180.0_8 C = COS(FRAD) S = SIN(FRAD) WRITE (*, 10) F, C, S10 FORMAT (F5.1, F12.8, F12.8) end doend PROGRAM PIN

Εκτέλεση του προγράμματος δίνει: 0.0 1.00000000 0.00000000

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 50

Page 51: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

0.1 0.99999848 0.00174533 0.2 0.99999391 0.00349065 0.3 0.99998629 0.00523596 0.4 0.99997563 0.00698126 0.5 0.99996192 0.00872654 0.6 0.99994517 0.01047178.....

Δευτέρα 19/5/2014 10:45-14:30, B' πολ. Μηχανικών, Προγραμματισμός Η/Υ, θεωρία, Α Τμήμα (01AB) Απόστροφοι σε κείμενο.A='Timoshenko's book' ! ΛΑΘΟΣΒάζω διπλές αποστρόφους για να αποφύγω το λάθοςA=”Timoshenko's book” ! ΣωστόΟι διπλές και απλές απόστροφοι είναι ισοδύναμες:A='EMP' και A=”EMP” κάνουν ακριβλως το ίδιο.Εναλλακτικά διπλασιάζω την απλή απόστροφο:A='Timoshenko''s book' ! Σωστό: 2 απλές απόστροφοι κολλητά μας κάνουνμία απόστροφο που δεν είναι delimeterΤο παρακάτω είναι επίσης σωστό, αφού delimeters είναι οι απλέςαπόστροφοι:A='Το μάθημα λέγεται “Προγραμματοισμός”'

FORMAT (κεφ. 6, 11 από το βιβλίο)Φορμά Iw, Fw.d, nX, AwΈνα προς ένα αντιστοιχία μεταξύ μεταβλητών και φορμά. Ένα προς ένα αντιστοιχία μεταξύ writeκαι σειρών που γράφονται (αναλόγως και με το read).Μιγαδικοί αριθμοί με δύο φορμά Fw.dΕπανάληψη φορμά: nIw, nFw.d, nAw (από τις επαναλήψεις μόνο αυτή μπορεί να χρησιμοποιηθείκαι να είναι ο κώδικας κατανοητός).ΠαραδείγματαΚείμενο σε φορμά (δεν συνιστάται).

Ανάγνωση με φορμά.Το φορμά F στο read να έχει πάντα μηδέν δεκαδικά ψηφία (πχ. F8.0).

Περισσότερα φορμά από μεταβλητές.Λιγότερα φορμά από μεταβλητές.

Επανάληψη πολλών φορμά με παρενθέσεις: n(Fw.d, Iw) (δεν συνιστάται).Επανάληψη FORMAT από την κοντινότερη αριστερή παρένθεση (δεν συνιστάται).Φορμά / (δεν συνιστάται).Φορμά BZ (δεν συνιστάται).Πάρα πολλά παραδείγματα.

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 51

Page 52: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

ΑΡΧΕΙΑΣύνταξη OPEN(unit, FILE=f, STATUS=s, IOSTAT=i)

ΠαράδειγμαΑντιγραφή αρχείων (3 σειρές από 2 ακέραιους σε κάθε σειρά) (πριν πω για STATUS)

PROGRAM COPYA implicit none integer :: i1, i2 OPEN (11, FILE='A.TXT') OPEN (12, FILE='B.TXT') READ (11, *) I1, I2 WRITE (12, *) I1, I2 READ (11, *) I1, I2 WRITE (12, *) I1, I2 READ (11, *) I1, I2 WRITE (12, *) I1, I2 CLOSE (11) CLOSE (12)END PROGRAM COPYA

Το πρώτο READ διαβάζει την πρώτη σειρά, το δεύτερο διαβάζει τη δεύτερη κλπ. Ομοίως το πρώτο WRITE γράφει την πρώτη σειρά, το δεύτερο γράφει τη δεύτερη κλπ.Δεν μπορεί να χρησιμοποιηθεί η ίδια μονάδα για δύο αρχεία (εκτός αν κλείσουμε το πρώτο αρχείο πριν ανοίξουμε το δεύτερο).

Στο μάθημα να εξηγηθεί η διαφορά statuls='old' και status='new':

PROGRAM COPYA implicit none integer :: i1, i2 OPEN (11, FILE='a.txt', status='old') OPEN (12, FILE='b.txt', status='new') READ (11, *) I1, I2 WRITE (12, *) I1, I2 READ (11, *) I1, I2 WRITE (12, *) I1, I2 READ (11, *) I1, I2 WRITE (12, *) I1, I2 CLOSE (11) CLOSE (12)END PROGRAM COPYA

Παρατηρούμε ότι μέρος του κώδικα επαναλαμβάνεται 3 φορές. Το αντικαθιστούμε με βρόχο:

PROGRAM COPYA implicit none integer :: i1, i2, i OPEN (11, FILE='a.txt', status='old') OPEN (12, FILE='b.txt', status='new') do i=1, 3

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 52

Page 53: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

READ (11, *) I1, I2 WRITE (12, *) I1, I2 end do CLOSE (11) CLOSE (12)END PROGRAM COPYA

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 53

Page 54: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Δευτέρα 26/5/2014 10:45-14:30, B' πολ. Μηχανικών, Προγραμματισμός Η/Υ, θεωρία, Α Τμήμα (01AB) ΠαράδειγμαΑντιγραφή ενός αρχείου (3 σειρές από 2 ακέραιους σε κάθε σειρά) σε 4 αρχεία

PROGRAM COPYB implicit none integer :: i1, i2, j OPEN (11, FILE='a1.txt') OPEN (12, FILE='a2.txt') OPEN (13, FILE='a3.txt') OPEN (14, FILE='a4.txt') OPEN (15, FILE='a5.txt') DO J=1, 3 READ (11, *) I1, I2 WRITE (12, *) I1, I2 WRITE (13, *) I1, I2 WRITE (14, *) I1, I2 WRITE (15, *) I1, I2 END DO CLOSE (11) CLOSE (12) CLOSE (13) CLOSE (14) CLOSE (15)END program copyb

Με χρήση βρόχων:

PROGRAM COPYB implicit none integer :: i1, i2, j, iun OPEN (11, FILE='a1.txt') OPEN (12, FILE='a2.txt') OPEN (13, FILE='a3.txt') OPEN (14, FILE='a4.txt') OPEN (15, FILE='a5.txt') DO J=1, 3 READ (11, *) I1, I2 do iun=12, 15 WRITE (iun, *) I1, I2 end do END DO do iun=11, 15 CLOSE (iun) end doEND program copyb

Με χρήση βρόχων και στο άνοιγμα αρχείων:

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 54

Page 55: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

PROGRAM COPYB implicit none integer :: i1, i2, j, iun character(len=20) :: fo, filnam fo = '(a, i1, a)' do iun=11, 15 j = iun - 10 write (filnam, fo) 'a', j, '.txt' OPEN (iun, FILE=filnam) end do DO J=1, 3 READ (11, *) I1, I2 do iun=12, 15 WRITE (iun, *) I1, I2 end do END DO do iun=11, 15 CLOSE (iun) end doEND program copyb

ΠαράδειγμαΑντιγραφή 3 αρχείων σε 1 (1 σειρά από ένα πραγματικό, 2 σειρές από 2 πραγματικούς, 3 σειρέςαπό 3 πραγματικούς, με δέκα θέσεις 2 δεκαδικά).Παράδειγμα δεδομένων στο αρχείο D.TXT είναι:

12.0 1.0 2.0 3.0 4.010.0 12.0 16.012.0 19.0 30.0 1.0 -12.0 16.0

program copyc implicit none integer, parameter :: iout=11, inp=12 integer :: i real :: x1, x2, x3 character(len=30) :: finp, fout open (iout, file='d.txt', status='new')

open (inp, file='a.txt', status='old') finp = '(f10.0)' fout = '(f10.2)' read (inp, finp) x1 write (iout, fout) x1 close (inp)

open (inp, file='b.txt', status='old') finp = '(f10.0, f10.0)'

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 55

Page 56: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

fout = '(f10.2, f10.2)' do i=1, 2 read (inp, finp) x1, x2 write (iout, fout) x1, x2 end do close (inp)

open (inp, file='c.txt', status='old') finp = '(f10.0, f10.0, f10.0)' fout = '(f10.2, f10.2, f10.2)' do i=1, 3 read (inp, finp) x1, x2, x3 write (iout, fout) x1, x2, x3 end do close (inp)

close (iout)end program copyc

Χρησιμοποιούμε μεταβλητές αντί για σταθερές στα READ, WRITE, OPEN, CLOSE που να έχουνόνομα που εκφράζει τη χρήση τους. Ακατανόητες σταθερές στο πρόγραμμα λέγονται υπερφυσικέςσταθερές (magic constants). Μία μονάδα αρχείου μπορούμε να τη χρησιμοποιήσουμε και σε άλλο αρχείο, αφού πρώτα τηνκλείσουμε. Επίσης στο μάθημα να εξηγηθεί ποια γραμμή ποιου αρχείου διαβάζει η κάθε READ καιγράφει η κάθε WRITE.

Παράδειγμα(Το παράδειγμα με τα ψώνια με χρήση αρχείου.)

Ανάγνωση/εγγραφή μεταβλητών χαρακτήρωνΑντί να γράφουμε στην οθόνη (*) ή σε κάποιο αρχείο μπορούμε να γράφουμε σε μεταβλητήχαρακτήρων. Δηλαδή, ειδικά για τα READ και WRITE, το unit μπορεί να είναι μία μεταβλητήχαρακτήρων. Σε αυτή την περίπτωση αντί να διαβάζεται και να γράφεται ένα αρχείο, 'διαβάζεται'και 'γράφεται' μία μεταβλητή. Για παράδειγμα: CHARACTER*80 ALINE X1 = 3.14 B=2.718 WRITE (DLINE, *) X1, BΤο περιεχόμενο της μεταβλητής DLINE μετά από το WRITE θα είναι ακριβώς το ίδιο με τοπεριεχόμενο που θα είχε η πρώτη σειρά του αρχείου, αν γραφόταν ένα αρχείο. Ομοίως: CHARACTER*80 ALINE ALINE = '999 134' READ (ALINE, *) J, KΟι τιμές που θα πάρουν οι μεταβλητές είναι 999 και 134 αντίστοιχα.

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 56

Page 57: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Σύνταξη εντολής OPEN:OPEN(unit, FILE=f, STATUS=s, FORM=t, IOSTAT=i)

unit=Ακέραια σταθερά ή μεταβλητήf, s=Σταθερά ή μεταβλητή χαρακτήρωνi = Ακέραια μεταβλητή (όχι σταθερά)s='UNKNOWN', 'NEW', 'OLD', 'APPEND', 'SCRATCH't='FORMATTED'T='UNFORMATTED'i == 0: Δεν έγινε λάθοςi /= 0: Έγινε κάποιο λάθος

Ομοίως:CLOSE (unit, STATUS=s, IOSTAT=i)s='KEEP' : διατηρεί το αρχείο (προεπιλεγμένη τιμή για όλα OPEN πλην

STATUS='SCRATCH''DELETE' : διαγράφει το αρχείο (προεπιλεγμένη τιμή OPEN με STATUS='SCRATCH')

REWIND (unit, IOSTAT=i)BACKSPACE (unit, IOSTAT=i)WRITE(....., IOSTAT=i)

Ειδικά για READ:READ(....., IOSTAT=i)i == 0 : Δεν έγινε λάθοςi < 0 : Έγινε λάθος: Το αρχείο τελείωσεi > 0 : Έγινε κάποιο άλλο λάθος

Παράδειγμα Μέσος όρος βαθμολογίας και τυπική απόκλιση. Στο αρχείο δεν υπάρχει ειδική τιμή που να δηλώνειτο τέλος του.

program aveg implicit none integer :: n, j real :: sum, am, b open (11, file='grades.txt', status='old') sum = 0.0 n = 0 do read (11, *, iostat=j) b if (j < 0) exit if (j > 0) stop 'syntax error' sum = sum + b n = n + 1 end do am = sum/real(n) write (*, *) am

close (11)

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 57

Page 58: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

open (11, file='grades.txt', status='old') !εναλλακτικά: !rewind (11) sum = 0.0 n = 0 do read (11, *, iostat=j) b if (j < 0) exit if (j > 0) stop 'syntax error' sum = sum + (b-am)**2 n = n + 1 end do write (*, *) sqrt(sum/real(n)) close (11)end program aveg

Παράδειγμα Σε αρχείο είναι γραμμένοι οι βαθμοί ενός μαθήματος. Στην πρώτη σειρά έχει γραφείο το όνομα τουμαθήματος (μέχρι 20 χαρακτήρες). Σε κάθε μία από τις επόμενες σειρές έχει γραφεί ο βαθμός κάθε φοιτητή. Στη συνέχεια έχει γραφεί η λέξη 'END'. Να υπολογιστεί ο μ.ο.Το περιεχόμενο του αρχείου θα μπορούσε να είναι το εξής:

ΜΑΘΗΜΑΤΙΚΑ5.58.09.03.07.5END

Ακολουθεί ο κώδικας:

program avegb implicit none integer :: n real :: sum, b, am character(len=20) :: aline, amath open (11, file='grades.txt', status='old') read (11, '(a)') amath sum = 0.0 n = 0 do read (11, *) aline if (aline == 'end') exit if (aline == 'END') exit read (aline, *) b sum = sum + b n = n + 1 end do am = sum/float(n) write (*, *) amath, ': average=', am

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 58

Page 59: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

close (11)end program avegb

ΠαράδειγμαΣτο προηγούμενο παράδειγμα, μετά το 'END' ακολουθεί το όνομα άλλου μαθήματος και στησυνέχεια οι βαθμοί, ένας σε κάθε σειρά. Στη συνέχεια έχει ξαναγραφεί 'END' και ακολουθούν καιάλλα μαθήματα. Να υπολογιστεί ο μ.ο. κάθε μαθήματος. Επίσης το όνομα του αρχείου θα δίνεταιαπό το πληκτρολόγιο

Το περιεχόμενο του αρχείου θα μπορούσε να είναι το εξής:

ΜΑΘΗΜΑΤΙΚΑ5.58.09.03.07.5ENDΑΝΤΟΧΗ ΥΛΙΚΩΝ6.57.08.04.03.5END

Κώδικας:

program avegb implicit none integer :: n, j real :: sum, b, am character(len=20) :: aline, amath, afn

do write (*, *) 'Δώστε όνομα αρχείου:' read (*, *) afn open (11, file=afn, status='old', iostat=j) if (j == 0) exit write (*, *) 'Το αρχείο', trim(afn), 'δεν μπορεί να προσπελαστεί' write (*, *) 'Προσπαθείστε πάλι.' end do

do read (11, '(a)', iostat=j) amath if (j < 0) exit if (j > 0) stop 'Κάποιο σοβαρό λάθος ανάγνωσης έγινε' sum = 0.0 n = 0 do read (11, *) aline if (aline == 'end') exit

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 59

Page 60: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

if (aline == 'END') exit read (aline, *) b sum = sum + b n = n + 1 end do am = sum/float(n) write (*, *) amath, ': average=', am end do close (11)end program avegb

Εκτέλεση του προγράμματος με τα παραπάνω δεδομένα δίνει:

ΜΑΘΗΜΑΤΙΚΑ : AVERAGE= 6.5999999 ΑΝΤΟΧΗ : AVERAGE= 5.8000002

Χρησιμοποιώντας συναρτήσεις το πρόγραμμα γίνεται πιο κατανοητό:

module modavimplicit nonecontains

integer function openData() integer :: j character(len=20) :: afn do write (*, *) 'Δώστε όνομα αρχείου:' read (*, *) afn open (11, file=afn, status='old', iostat=j) if (j == 0) exit write (*, *) 'Το αρχείο', trim(afn), 'δεν μπορεί να προσπελαστεί' write (*, *) 'Προσπαθείστε πάλι.' end do openData = 0end function openData

real function avMath() integer :: n real :: sum, b, am character(len=20) :: aline sum = 0.0 n = 0 do read (11, *) aline if (aline == 'end') exit if (aline == 'END') exit read (aline, *) b sum = sum + b n = n + 1 end do

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 60

Page 61: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

avMath = sum/float(n)end function avMath

end module modav

program avegb use modav implicit none integer :: j character(len=20) :: amath

j = openData() do read (11, '(a)', iostat=j) amath if (j < 0) exit if (j > 0) stop 'Κάποιο σοβαρό λάθος ανάγνωσης έγινε' write (*, *) amath, ': average=', avMath() end do close (11)end program avegb

Στο παραπάνω πρόγραμμα παρατηρείστε ότι μία συνάρτηση μπορεί να μην έχει εικονικέςπαραμέτρους καθόλου.

ΠαράδειγμαΣε αρχείο SKYR.TXT στην πρώτη σειρά είναι γραμμένο το πλήθος δοκιμίων σε 3 στήλες. Σε κάθεμία από τις επόμενες σειρές είναι γραμμένη η αντοχή ενός δοκιμίου σε δέκα στήλες με 1 δεκαδικό.Να βρεθεί ο μ.ο. των αντοχών δοκιμίων. Να απορριφθούν δοκίμια που αποκλίνουν από το μέσοόρο >= 5MPa. Να βρεθεί ο μ.ο. με τα δοκίμια που απομένουν.

PROGRAM SKYR implicit none integer :: n, i real :: sum, fmes, f OPEN (11, FILE='SKYR.TXT', STATUS='OLD') READ (11, *) N !Λάθος: 3 θέσεις λέει το θέμα SUM = 0.0 DO I=1, N READ (11, '(f10.1)') F !Πιθανό λάθος: ανάγνωση με 1 δεκαδικό SUM = SUM + F END DO FMES = SUM/N !Λάθος: μικτή WRITE (*, '(a, F10.1)') 'ΜΕΣΟΣ ΟΡΟΣ=', FMES REWIND (11) READ (11, '(i3)') N DO I=1, N READ (11, '(f10.1)') F !Πιθανό λάθος: ανάγνωση με 1 δεκαδικό IF (F-FMES >= 5.0) THEN !Λάθος:χρειάζεται abs SUM = SUM - F N = N - 1 !Λάθος: αλλαγή ορίου DO

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 61

Page 62: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

WRITE (*, '(a, f10.1, a)') 'ΤΟ ΔΟΚΙΜΙΟ ΜΕ ΑΝΤΟΧΗ', F, & ' ΑΠΟΡΡΙΠΤΕΤΑΙ' END IF END DO FMES = SUM/N !Λάθος: μικτή WRITE (*, '(a, F10.1)') 'ΜΕΣΟΣ ΟΡΟΣ=', FMES CLOSE (11)END program skyrΟρθός κώδικας:

PROGRAM SKYR implicit none integer :: n, i, m real :: sum, fmes, f OPEN (11, FILE='SKYR.TXT', STATUS='OLD') READ (11, '(i3)') N SUM = 0.0 DO I=1, N READ (11, '(f10.0)') F SUM = SUM + F END DO FMES = SUM/real(N) WRITE (*, '(a, F10.1)') 'ΜΕΣΟΣ ΟΡΟΣ=', FMES REWIND (11) READ (11, '(i3)') N m = n DO I=1, N READ (11, '(f10.0)') F IF (abs(F-FMES) >= 5.0) THEN SUM = SUM - F m = m - 1 WRITE (*, '(a, f10.1, a)') 'ΤΟ ΔΟΚΙΜΙΟ ΜΕ ΑΝΤΟΧΗ', F, & ' ΑΠΟΡΡΙΠΤΕΤΑΙ' END IF END DO FMES = SUM/real(m) WRITE (*, '(a, F10.1)') 'ΜΕΣΟΣ ΟΡΟΣ=', FMES CLOSE (11)END program skyr

ΠαράδειγμαΣτο αρχείο COP1.TXT να γραφούν οι δυνάμεις του 2 που δεν ξεπερνούν το 1000. Στο COP3.TXT,οι δυνάμεις του 3 κλπ μέχρι το αρχείο COP9.TXT.

PROGRAM DYN implicit none integer :: i, k OPEN (11, FILE='COP2.TXT', STATUS='NEW') DO I=1, 10000 K = 2**I IF (K > 1000) EXIT WRITE (11, *) K

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 62

Page 63: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

END DO CLOSE (11) OPEN (11, FILE='COP3.TXT', STATUS='NEW') DO I=1, 10000 K = 3**I IF (K > 1000) EXIT WRITE (11, *) K END DO CLOSE (11) !....end program dyn

Το άνοιγμα των αρχείων μπορεί να αυτοματοποιηθεί χρησιμοποιώντας τη δυνατότητα της Fortranνα “γράφει” σε μεταβλητές χαρακτήρων όπως ακριβώς γράφει στην οθόνη και στα αρχεία:

PROGRAM DYN2 implicit none integer :: jbase, i, k CHARACTER(len=80) :: afn DO jbase=2, 9 WRITE (afn, '(A, I1, A)') 'COP', jbase, '.TXT' OPEN (11, FILE=afn, STATUS='NEW') i = 0 DO i = i + 1 K = jbase**I IF (K > 1000) EXIT WRITE (11, *) K END DO CLOSE (11) END DOEND program dyn2

Σύνταξη του WRITE:1. WRITE (*, ...) ... Η εκτύπωση γίνεται στην οθόνη2. WRITE (11, ...) ... ή WRITE (K, ...) ... όπου K ακέραια μεταβλητή Η εκτύπωση γίνεται στο αρχείο που έχει ανοιχτεί με τη μονάδα 11 ή τη μονάδα που έχει

αποθηκευθεί στην ακέραια μεταβλητή K.2. WRITE (A, ...) όπου A μεταβλητή χαρακτήρων (κειμένου) ή και πίνακας χαρακτήρων Η εκτύπωση γίνεται στη μεταβλητή χαρακτήρων. Η μεταβλητή χαρακτήρων παίρνει ως τιμήαυτά που θα τυπώνονταν στην οθόνη αν αντί για A είχαμε βάλει *.Αντίστοιχα ισχύουν και για την εντολή READ.

ΠαράδειγμαΝα φτιάξετε μία συνάρτηση η οποία να δέχεται έναν 4ψήφιο θετικό ακέραιο και να επιστρέφει τοναριθμό αυτό με τα ψηφία του αντίστροφα, χρησιμοποιώντας βοηθητικό αρχείο. Για παράδειγμα οαριθμός 1257 να δίνει 7521.

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 63

Page 64: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

module modantimplicit nonecontains

integer FUNCTION IANT(J) integer :: j integer :: k1, k2, k3, k4 character(len=30), parameter :: fo1 = '(i4)', fo4='(I1, I1, I1, I1)' OPEN (11, FILE='TEMP.TXT', STATUS='NEW') WRITE (11, fo1) J REWIND (11) READ (11, fo4) K1, K2, K3, K4 REWIND (11) WRITE (11, fo4) K4, K3, K2, K1 REWIND (11) READ (11, fo1) iant CLOSE (11, status='delete')END function iant

end module modant

PROGRAM XXX use modant implicit none integer :: k K = 9876 WRITE (*, *) K, iant(k) K = 3141 WRITE (*, *) K, iant(k)END program xxx

Το αρχείο TEMP.TXT είναι αυθαίρετο και μπορεί να οδηγήσει σε επιπλοκές αν υπάρχει.Προτιμότερο είναι να χρησιμοποιήσουμε προσωρινό αρχείο (SCRATCH) το οποίο είναι εγγυημένοότι δεν υπάρχει και επίσης διαγράφεται αυτόματα όταν το κλείνουμε:

integer FUNCTION IANT(J) integer :: j integer :: k1, k2, k3, k4 character(len=30), parameter :: fo1 = '(i4)', fo4='(I1, I1, I1, I1)' OPEN (11, STATUS='SCRATCH') WRITE (11, fo1) J REWIND (11) READ (11, fo4) K1, K2, K3, K4 REWIND (11) WRITE (11, fo4) K4, K3, K2, K1 REWIND (11) READ (11, fo1) iant CLOSE (11) !διαγράφεται αυτόματαEND function iant

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 64

Page 65: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Επειδή γράφουμε μόνο μία σειρά στο αρχείο είναι πολύ προτιμότερο, πιο γρήγορο και πιοευανάγνωστο να γράφουμε και να διαβάζουμε από μεταβλητή χαρακτήρων αντί για αρχείο:

integer FUNCTION IANT(J) integer :: j integer :: k1, k2, k3, k4 character(len=30), parameter :: fo1 = '(i4)', fo4='(I1, I1, I1, I1)' character(len=4) :: a OPEN (11, STATUS='SCRATCH') WRITE (a, fo1) J READ (a, fo4) K1, K2, K3, K4 WRITE (a, fo4) K4, K3, K2, K1 READ (a, fo1) iantEND function iant

Έμμεσος βρόχος κατά την εγγραφή ή ανάγνωση αρχείου.

ΠαράδειγμαΝα συντάξετε πρόγραμμα που να γράφει σε μία σειρά του αρχείου “AR” του αριθμούς από το 2έως το 20 ανά 2, καθώς επίσης και το τετράγωνό του. Το κάθε νούμερο να γράφεται σε 4 θέσεις.

PROGRAM S OPEN (11, FILE='AR', STATUS='NEW') WRITE (11, 10) (J, J**2, J=2, 20, 2)10 FORMAT (20I4) CLOSE (11) STOP END

ΠαράδειγμαΝα συντάξετε πρόγραμμα που να γράφει σε μία σειρά του αρχείου “AR” του αριθμούς από το 2έως το 20 ανά 2, καθώς επίσης και το τετράγωνό του. Το κάθε νούμερο να γράφεται σε 4 θέσεις.Στη δεύτερη σειρά να γράφει τους αριθμούς 22-40 ανά 2, στην τρίτη τους 42-60 ανά 2 κλπ μέχρι τη26η σειρά.

program s open (11, file='ar', status='new') do k=1, 26 write (11, '(20i7)') ((K-1)*20+J, ((K-1)*20+J)**2, J=2, 20, 2) end do close (11)end program s OPEN (11, FILE='AR', STATUS='NEW')

Εναλλακτικά:

program s open (11, file='ar', status='new') k1 = 0 do k=1, 26 write (11, '(20i7)') (k1+j, (k1+j)**2, j=2, 20, 2) k1 = k1 + 20

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 65

Page 66: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

end do close (11)end program s

Δευτέρα 2/6/2014 10:45-14:30, B' πολ. Μηχανικών, Προγραμματισμός Η/Υ, θεωρία, Α Τμήμα (01AB) ΠαράδειγμαΝα συντάξετε πρόγραμμα που να διαβάζει και να τυπώνει το τέταρτο πραγματικό αριθμό τουαρχείου PAR.TXT.

program tet1 implicit none real :: a, b, c, d open (11, file='par.txt', status='old') read (11, *) a, b, c, d write (*, *) d close (11)end program tet1

Χωρίς σπατάλη μεταβλητών:

program tet2 implicit none real :: d open (11, file='par.txt', status='old') read (11, *) d, d, d, d write (*, *) d close (11)end program tet2

Χωρίς σπατάλη μεταβλητών με έμμεσο βρόχο:

program tet3 implicit none integer :: i real :: d open (11, file='par.txt', status='old') read (11, *) (d, i=1, 4) write (*, *) d close (11)end program tet2

ΠαράδειγμαΝα συντάξετε πρόγραμμα που να βρίσκει και να τυπώνει το υψόμετρο σημείου με συντεταγμένες x,y που διαβάζονται από το πληκτρολόγιο. Σε αρχείο ATHINA.DEM στην πρώτη γραμμή έχουνγραφεί οι συντεταγμένες του πάνω αριστερά σημείου του κανάβου. Στη δεύτερη γραμμή έχουνγραφεί dx, dy τα βήματα του κανάβου. Στην τρίτη σειρά το πλήθος των στηλών nx και το πλήθοςτων γραμμών ny έχει ο κάναβος.

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 66

Page 67: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

program kan implicit none real :: x, y, xpa, ypa, dx, dy, h integer :: nxcols, nyrows, jx, iy, i, j read (*, *) x, y open (11, file='athina.dem', status='old') read (11, *) xpa, ypa read (11, *) dx, dy read (11, *) nxcols, nyrows jx = int((x-xpa)/dx) + 1 iy = int((y-ypa)/dy) + 1 do i=1, iy read (11, *) (h, j=1, jx) end do write (*, *) h close (11)end program kan

Υποπρογράμματα τύπου υπορουτίνας (SUBROUTINE).

REAL FUNCTION SSS (V1, V2, ..)....SSS = .......END FUNCTION SSS

SUBROUTINE SSS (V1, V2, ...)....END SUBROUTINE SSS

ΚλήσηA = SSS(V1, V2, ...)Επιστρέφει μία τιμή

ΚλήσηCALL SSS(V1, V2, ...)Επιστρέφει 2 ή περισσότερες τιμέςΜπορεί να μην επιστρέφει καμμία

Έννοιες. Για αποφυγή επανάληψης κώδικα. Αρχικά για οικονομία μνήμης υπολογιστής καιμηχανικού. Τώρα κυρίως για να αποφεύγονται λάθη καυτά την επανάληψη. Επίσης σπάμε τοπρόγραμμα σε κομμάτια -> λιγότερα πολύπλοκα -> λιγότερος χρόνος (μη γραμμική σχέση αριθμώνσειρών και χρόνου). Επίσης μοιρασιά σε πολλούς προγραμματιστές.Όλες οι μεταβλητές ανεξάρτητες από κύριο πρόγραμμα.Το υποπρόγραμμα SUBROUTINE διαφέρει από το υποπρόγραμμα FUNCTION στο ότι ηSUBROUTINE μπορεί να μην επιστρέφει τίποτα, ή να επιστρέφει παραπάνω από 2 τιμές.Επικοινωνία με ενεργές παραμέτρους και εικονικές παραμέτρους. Γίνεται κάτι σαν αντιγραφή.Μεταβλητές IN και INOUT. Στις IN μπορεί να μπει σταθερά ή αριθμητική παράσταση.Υποπρογράμματα SUBROUTINE και FUNCTION. Στα FUNCTION συνήθως επιτρέπουμεμεταβλητές IN μόνο.

ΠαράδειγμαΝα συντάξετε υποπρόγραμμα που να τυπώνει πίνακα οπλισμού πλάκας με διάμετρο οπλισμού Φmm (ακέραιος αριθμός) και αποστάσεις ράβδων s από 4–10 cm ανά 0.5cm και από 10-25cm ανά1cm. Να τυπώσετε πίνακα για Φ8, Φ10 και Φ12.

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 67

Page 68: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

n = πλήθος ράβδων σε 100 cm = 100/sAΦ = εμβαδόν διατομής μίας ράβδου σε cm2 = πΦ2/4Α = εμβαδόν ράβδων Φ/s σε cm2 = n ΑΦ = 100/s ΑΦ

module modoplimplicit nonecontains

integer function ipin(KF) integer :: KF real :: af, s, a af = 3.14159 * (real(KF)/10.0)**2 / 4.0 s = 4.0 do while (s < 9.75) a = 100.0/s * af write (11, '(a, i2, a, f4.1, a, f6.2)') 'Φ', KF, '/', s, ': ', a s = s + 0.5 end do s = 10.0 do while (s < 25.5) a = 100.0/s * af write (11, '(a, i2, a, f4.1, a, f6.2)') 'Φ', KF, '/', s, ': ', a s = s + 1.0 end do ipin = 0end function ipin

end module modopl

program plakes use modopl implicit none integer :: i open (11, file='plakes.txt') i = ipin(8) i = ipin(10) i = ipin(12) close (11)end program plakes

Επειδή η συνάρτηση πρέπει υποχρεωτικά να επιστρέψει μία τιμή, επιστρέφει μία αυθαίρετη πουμπορεί να μπερδέψει όποιον το διαβάζει. Η σωστή λύση είναι να χρησιμοποιηθεί SUBROUTINE:

module modoplimplicit nonecontains

subroutine pin(KF) integer, intent(IN) :: KF real :: af, s, a af = 3.14159 * (real(KF)/10.0)**2 / 4.0 s = 4.0

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 68

Page 69: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

do while (s < 9.75) a = 100.0/s * af write (11, '(a, i2, a, f4.1, a, f6.2)') 'Φ', KF, '/', s, ': ', a s = s + 0.5 end do s = 10.0 do while (s < 25.5) a = 100.0/s * af write (11, '(a, i2, a, f4.1, a, f6.2)') 'Φ', KF, '/', s, ': ', a s = s + 1.0 end doend subroutine pin

end module modopl

program plakes use modopl implicit none open (11, file='plakes.txt') call pin(8) call pin(10) call pin(12) close (11)end program plakes

Στην περίπτωση υπορουτίνας κάθε παράμετρος μπορεί να εισάγει μία τιμή στην υπορουτίνα, ή ναυπολογίζεται από την υπορουτίνα. Στο παραπάνω παράδειγμα η παράμετρος KF εισάγει μία τιμήπου χρησιμοποιεί η υπορουτίνα για να υπολογίζει το εμβαδόν AF. Πουθενά στην υπορουτίνα δενυπάρχει εντολή:

KF = ..... ήREAD (..., ...) KF

και έτσι η KF δεν αλλάζει τιμή κατά την εκτέλεση της υπορουτίνας. Τέτοιες παράμετροι λέγονταιIN και πρέπει (συνιστάται θερμώς) να ορίζονται με την επιλογή INTENT(IN): integer, intent(IN) :: KFΟι ενεργές παράμετροι (οι παράμετροι της υπορουτίνας κατά την κλήση της υπορουτίνας – actualarguments) μπορεί να είναι μεταβλητές, σταθερές ή ακόμα και ολόκληρες παραστάσεις: call pin(8) call pin(L) call pin(L**2+12)Αν μία παράμετρος (οι παράμετροι που γράφονται στην εντολή SUBROUTINE λέγονται εικονικές– dummy arguments), αλλάζει τιμή κατά την εκτέλεση της υπορουτίνας, λέγεται OUT και πρέπει(συνιστάται θερμώς) να ορίζεται με την επιλογή INTENT(OUT): real, intent(OUT) :: AVΟι ενεργές παράμετροι OUT (οι παράμετροι της υπορουτίνας κατά την κλήση της υπορουτίνας)πρέπει υποχρεωτικά να είναι μεταβλητές (είναι πολύ σοβαρό λάθος να μην είναι μεταβλητές, ήπίνακες όπως θα δούμε παρακάτω).Τέλος αν μία εικονικής παράμετρος εισάγει μία τιμή στην υπορουτίνα (για παράδειγμαχρησιμοποιείται σε κάποιον υπολογισμό) και στη συνέχεια αλλάζει τιμή είτε με ανάθεση (=) είτε μεανάγνωση (READ), λέγεται INOUT και πρέπει (συνιστάται θερμώς) να ορίζεται με την επιλογήINTENT(OUT): real, intent(INOUT) :: SUM

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 69

Page 70: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Οι ενεργές παράμετροι INOUT (οι παράμετροι της υπορουτίνας κατά την κλήση της υπορουτίνας)πρέπει υποχρεωτικά να είναι μεταβλητές (είναι πολύ σοβαρό λάθος να μην είναι μεταβλητές, ήπίνακες όπως θα δούμε παρακάτω). Γενικώς παράμετροι INOUT πρέπει να αποφεύγονται όπουείναι δυνατό, για την βελτίωση της αναγνωσιμότητας του προγράμματος.

Μπορεί να θεωρηθεί ότι πριν ξεκινήσει η εκτέλεση του υποπρογράμματος οι ενεργές παράμετροιIN και INOUT αντιγράφονται στις αντίστοιχες εικονικές παραμέτρους. Επίσης, ακριβώς μετά τηνολοκλήρωση της εκτέλεσης του υποπρογράμματος, οι εικονικές παράμετροι OUT και INOUTαντιγράφονται στις ενεργές παραμέτρους.

Παράδειγμα.Να συντάξετε υποπρόγραμμα που να υπολογίζει την ελάχιστη τη μέγιστη και τη μέση αντοχήδοκιμίων.

Επειδή πρέπει να υπολογιστούν και να επιστραφούν περισσότερες από 1 τιμή θα χρησιμοποιηθείSUBROUTINE:

module modmmavimplicit nonecontains

subroutine mmav(iun, fmax, fmin, fav) integer, intent(in) :: iun real, intent(out) :: fmax, fmin, fav real :: sum, f integer :: j, n fmax = 0.0 fmin = 1.0e30 sum = 0.0 n = 0 do read (iun, *, iostat=j) f if (j < 0) exit if (j > 0) stop 'Syntax error' if (f > fmax) fmax = f if (f < fmin) fmin = f sum = sum + f n = n + 1 end do fav = sum/float(n)end subroutine mmav

end module modmmav

program zzz use modmmav real :: anmax, anmin, anav open (11, file='dok.txt', status='old') call mmav(11, anmax, anmin, anav)

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 70

Page 71: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

write (*, *) anmax, anmin, anav close (11)end program zzz

Πριν από το RETURN οι εικονικές μεταβλητές INOUT (και OUT) “αντιγράφονται” στιςπραγματικές.

ΠαράδειγμαΣτο αρχείο A.TXT έχουν γραφεί οι αντοχές δοκιμίων που λήφθησαν από μία παρτίδασκυροδέματος, μία σε κάθε σειρά. Να υπολογιστεί και να εκτυπωθεί με ένα δεκαδικό στην οθόνη ημέση αντοχή fm, η τυπική απόκλιση σ των δοκιμίων και η χαρακτηριστική αντοχή τουσκυροδέματος fck=fm-1,64σ. Στη συνέχεια να γίνει το ίδιο για άλλες 2 παρτίδες σκυροδέματος στααρχεία B.TXT και C.TXT.

Θα συνταχθεί υπορουτίνα που υπολογίζει τις τρεις τιμές και θα κληθεί 3 φορές για τα αρχείααντίστοιχα.module modconcimplicit nonecontainssubroutine concrete (afn) character(len=*), intent(in) :: afn integer :: n, j real :: f, sum, fm, s, fyk open (11, file=afn, status='old') sum = 0.0 n = 0 do read (11, *, iostat=j) f if (j < 0) exit if (j > 0) stop 'Συντ. λάθος' sum = sum + f n = n + 1 end do fm = sum / real(n) sum = 0.0 rewind (11) do read (11, *, iostat=j) f if (j < 0) exit if (j > 0) stop 'Συντ. λάθος' sum = sum + (f-fm)**2 end do s = sqrt(sum/real(n)) fyk = fm - 1.64*s write (*, 10) afn, fm, s, fyk10 format (a20, f10.1, f10.1, f10.1) close (11)end subroutine concrete

end module modconc

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 71

Page 72: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

program tria use modconc implicit none call concrete ('a.txt') call concrete ('b.txt') call concrete ('c.txt')end program tria

Το * στην εντολή character(len=*) μπορεί να μπει μόνο σε εικονικές παραμέτρους (ή σεονοματισμένες σταθερές).

Παλιό θέμαΝα συνταχθεί πρόγραμμα σε Fortran το οποίο να υπολογίζει και να τυπώνει με τρία δεκαδικά τηνταχύτητα του νερού V και την παροχή Q σε ανοιχτό αγωγό πλάτους b, βάθους ροής h, συντελεστήτριβής n και κλίσης s:

Rh=bh

b+2h , V=

1n

Rh2/3 s1 /2

, Q=V bh

για τις ακόλουθες τιμές της μεταβλητής h: 0.1, 0.3, 3.14, 2.71Το πρόγραμμα να διαβάζει τις τιμές των σταθερών n, b, s από το πληκτρολόγιο. Όλες οι μεταβλητέςκαι όλες οι σταθερές είναι πραγματικοί αριθμοί.

(2 μονάδες)

Προσοχή: Οι τιμές 0.1, 0.3, 3.14, 2.71 δεν υπάρχουν σε κάποιο αρχείο ούτε δίνονται από τοπληκτρολόγιο.

Κώδικας:

module modqvimplicit nonecontains

subroutine par(an, b, s, h, q, v) real, intent(in) :: an, b, s, h real, intent(out) :: q, v real :: rh rh = b*h / (b + 2.0*h) v = rh**(2.0/3.0) * sqrt(s) / an q = v * b * hend subroutine par

subroutine write (an, b, s, h) real, intent(in) :: an, b, s, h real :: q, v character(len=30) :: fo fo = '(f10.3, f10.3, f10.3)' call par(an, b, s, h, q, v) write (*, fo) h, q, vend subroutine write

end module modqv

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 72

Page 73: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

program qv1 use modqv implicit none real :: an, b, s read (*, *) an, b, s call write(an, b, s, 0.1) call write(an, b, s, 0.3) call write(an, b, s, 3.14) call write(an, b, s, 2.71)end program qv1

Παρατηρούμε ότι μία υπορουτίνα έχει ονομαστεί WRITE που είναι το ίδιο όνομα με μία εντολή τηςFortran. Αυτό επιτρέπεται, αλλά πρέπει να αποφεύγεται γιατί μπορεί να παρερμηνευτεί.Για να γλυτώσουμε την επανάληψη πολλών παραμέτρων σε κάθε κλήση των υπορουτίνωντοποθετούμε τις μεταβλητές που δεν αλλάζουν στην module:

module modqvimplicit nonereal :: an, b, scontains

subroutine par(h, q, v) real, intent(in) :: h real, intent(out) :: q, v real :: rh rh = b*h / (b + 2.0*h) v = rh**(2.0/3.0) * sqrt(s) / an q = v * b * hend subroutine par

subroutine wr (h) real, intent(in) :: h real :: q, v character(len=30) :: fo fo = '(f10.3, f10.3, f10.3)' call par(h, q, v) write (*, fo) h, q, vend subroutine wr

end module modqv

program qv2 use modqv implicit none read (*, *) an, b, s call wr(0.1) call wr(0.3) call wr(3.14) call wr(2.71)end program qv2

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 73

Page 74: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

ΆσκησηΝα διορθώσετε υφιστάμενο πρόγραμμα το οποίο υπολογίζει και χρησιμοποιεί τον οπλισμό As (cm2)δοκού, έτσι ώστε ο οπλισμός As να είναι ακέραιο πολλαπλάσιο του εμβαδού ράβδου F18 (mm). Οοπλισμός στρογγυλεύεται προς τα πάνω.program skyr....real :: As, g, .........As = opl(....)g = As/100.0 * 7800.0....end program skyr

Η στρογγυλοποίηση θα χρειαστεί κάποιες μεταβλητές, και για να μην μπλέξουν με μεταβλητές μετο ίδιο όνομα στο υφιστάμενο πρόγραμμα φτιάχνουμε υπορουτίνα:

module modstrogimplicit nonecontains

subroutine strog (As) real, intent(inout) :: As real :: af, pi integer :: n pi = 3.14159 af = pi * 1.8**2/4.0 n = int(As/af + 0.9999) as = real(n) * afend subroutine strog

end module modstrog

program skyruse modstrog....real :: As, g, .........As = opl(....)call strog(As)g = As/100.0 * 7800.0....end program skyr

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 74

Page 75: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

ΜΗΤΡΩΑ (ΠΙΝΑΚΕΣ)Πολλές φορές πολλά δεδομένα χρειάζονται σε πολλά τμήματα ενός προγράμματος. Όμως ΔΕΝμπορούμε να διαβάζουμε ένα-ένα νούμερο σε μία και μοναδική μεταβλητή. Για παράδειγμα ο μ.ο.και η απόκλιση 3 αριθμών με μία μεταβλητή οδηγεί σε λάθη:

program test1 implicit none real :: sum, a, av, s sum = 0.0 read (*, *) a sum = sum + a read (*, *) a sum = sum + a read (*, *) a sum = sum + a av = sum/3.0 write (*, *) av sum = 0.0 sum = sum + (a-av)**2 !ΛΑΘΟΣ sum = sum + (a-av)**2 !ΛΑΘΟΣ sum = sum + (a-av)**2 !ΛΑΘΟΣ s = sqrt(sum/3.0) write (*, *) send program test1

(Στην αίθουσα να γίνει πίνακας με τις τιμές των μεταβλητών κατά την εκτέλεση). Κατά τονυπολογισμό της απόκλισης S η μεταβλητή A έχει τον τελευταίο διαβασμένο αριθμός, ο οποίοςπροστίθεται 3 φορές. Ο σωστός τρόπος είναι να αποθηκεύσουμε κάθε αριθμό σε ΔΙΑΦΟΡΕΤΙΚΗμεταβλητή:

program test2 implicit none real :: sum, a, b, c, av, s sum = 0.0 read (*, *) a sum = sum + a read (*, *) b sum = sum + b read (*, *) c sum = sum + c av = sum/3.0 write (*, *) av sum = 0.0 sum = sum + (a-av)**2 !ΛΑΘΟΣ sum = sum + (b-av)**2 !ΛΑΘΟΣ sum = sum + (c-av)**2 !ΛΑΘΟΣ s = sqrt(sum/3.0) write (*, *) send program test2

Τι γίνεται όμως αν χρειάζεται να υπολογιστεί η τυπική απόκλιση για 20 μεταβλητές, ή αν αυτόφαίνεται εφικτό, για 20000 μεταβλητές. Δημιουργείται το πρόβλημα να βρούμε ονόματα για αυτές

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 75

Page 76: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

τις 20000 μεταβλητές, και δεύτερον ο κώδικας που απαιτείται είναι τεράστιος και, αν εξαιρέσουμετο όνομα της μεταβλητές, επαναλαμβανόμενος (και συνεπώς επιρρεπής σε λάθη).Χρειάζεται κάποιος τρόπος για μαζικό ορισμό μεταβλητών και κάποιος συστηματικός τρόπος γιανα τις χειριζόμαστε. Αυτός ο τρόπος είναι ο ορισμός πινάκων (ή μητρώων).Στη Fortran (και σε άλλες γλώσσες προγραμματισμού) ένας πίνακας (array) είναι ένα σύνολοπολλών μεταβλητών με το ίδιο όνομα. Ορίζεται με την ιδιότητα (attribute) DIMENSION πουτοποθετείται στην εντολή που καθορίζει τον τύπο μίας μεταβλητής:

REAL, DIMENSION(100) :: DΗ παραπάνω εντολή ορίζει ότι το D είναι ένας πίνακας που συνίσταται από 100 πραγματικέςμεταβλητές . Κάθε μία από αυτές τις μεταβλητές έχει έναν αύξοντα αριθμό που λέγεται δείκτης καικυμαίνεται από 1 έως 100. Για να χειριστούμε μία από τις μεταβλητές του πίνακα, γράφουμε τοόνομα του πίνακα με το δείκτη μέσα σε παρενθέσεις δίπλα. Για παράδειγμα για να θουμε μία τιμήκαι να τυπώσουμε την 16η μεταβλητή του πίνακα:

D(16) = 3.14159WRITE (*, *) D(16)

Προσοχή, στη Fortran ο δείκτης πρέπει να περικλείεται από παρενθέσεις και όχι αγκύλες όπως σεάλλες γλώσσες προγραμματισμού. Ένας δείκτης που περικλείεται από αγκύλες σημαίνει κάτιτελείως διαφορετικό στη Fortran (την αντίστοιχη διεργασία στα πλαίσια του παράλληλουπρογραμματισμού.Με πίνακες το παράδειγμα με τον υπολογισμό της τυπικής απόκλισης γίνεται:

program test3 implicit none real :: sum, av, s real, dimension(3) :: d sum = 0.0 read (*, *) d(1) sum = sum + d(1) read (*, *) d(2) sum = sum + d(2) read (*, *) d(3) sum = sum + d(3) av = sum/3.0 write (*, *) av sum = 0.0 sum = sum + (d(1)-av)**2 !ΛΑΘΟΣ sum = sum + (d(2)-av)**2 !ΛΑΘΟΣ sum = sum + (d(3)-av)**2 !ΛΑΘΟΣ s = sqrt(sum/3.0) write (*, *) send program test3

(Στην αίθουσα να γίνει πίνακας με τις τιμές των μεταβλητών κατά την εκτέλεση).

Το πρόγραμμα αυτό είναι τελείως ισοδύναμο με το αρχικό, και στην πραγματικότητα μοντέρνοιμεταγλωττιστές βέλτιστου κώδικα (optimising compilers) θα παράγουν τον ίδιο κώδικα μηχανής.Βέβαια, ο ορισμός ενός πίνακα, δηλαδή πολλών μεταβλητών με το ίδιο όνομα που ξεχωρίζουνμεταξύ τους με το δείκτη, δίνει δυνατότητα αποφυγής επαναλαμβανόμενου κώδικα, και έτσι τοπρόγραμμα γίνεται:

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 76

Page 77: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

program test4 implicit none real :: sum, av, s real, dimension(3) :: d integer :: i sum = 0.0 do i=1, 3 read (*, *) d(i) sum = sum + d(i) end do av = sum/3.0 write (*, *) av sum = 0.0 do i=1, 3 sum = sum + (d(i)-av)**2 end do s = sqrt(sum/3.0) write (*, *) send program test4

Το πλήθος των μεταβλητών ενός πίνακα λέγεται διάσταση του πίνακα και πρέπει να είναι μίασταθερά. Δεν μπορούμε να ορίσουμε για παράδειγμα:

PROGRAM TEST REAL, DIMENSION(N) :: D !ΛΑΘΟΣ ...

Τι έχει μέσα η μεταβλητή N; Δεν βάλαμε κάποια τιμή στη N. Αλλά και να είχαμε βάλει πάλι θαήταν λάθος:

PROGRAM TEST INTEGER :: N N = 100 REAL, DIMENSION(N) :: D !ΛΑΘΟΣ (πρέπει να πάει μετά το INTEGER) ...

Όπως έχει τονιστεί, οι ορισμοί των μεταβλητών γίνονται ΠΡΙΝ από τις εκτελέσιμες εντολές.Υπάρχει τρόπος να γίνει, ορίζοντας τον πίνακα με την ιδιότητα ALLOCATABLE, χωρίς καμμίαμεταβλητή, και στη συνέχεια ορίζεται το πλήθος των μεταβλητών (διάσταση του πίνακα) σε μίαεντολή ALLOCATE:

PROGRAM TEST3 INTEGER :: N REAL, ALLOCATABLE, DIMENSION(:) :: D N = 100 ALLOCATE (D(N)) ...

Μία από τις μεταβλητές του πίνακα ονομάζεται και 'στοιχείο' του πίνακα. Μία μεταβλητή που δενείναι πίνακας ονομάζεται βαθμωτή μεταβλητή. Τέλος πρέπει να τονιστεί ότι οι πίνακες της FortranΔΕΝ είναι μαθηματικά μητρώα ή διανύσματα, είναι απλώς ένα σύνολο ομοειδών μεταβλητών καιτίποτα παραπάνω.

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 77

Page 78: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

ΆσκησηΣε αρχείο SKYR.TXT στην πρώτη σειρά είναι γραμμένο το πλήθος δοκιμίων σε 3 στήλες. Σε κάθεμία από τις επόμενες σειρές είναι γραμμένη η αντοχή ενός δοκιμίου σε δέκα στήλες με 1 δεκαδικό.Να βρεθεί ο μ.ο. των αντοχών δοκιμίων. Να απορριφθούν δοκίμια που αποκλίνουν από το μέσοόρο >= 5MPa. Να βρεθεί ο μ.ο. με τα δοκίμια που απομένουν.

Στο προηγούμενο παράδειγμα για αντοχές δοκιμίων σκυροδέματος, ήταν αναγκαίο ναξαναδιαβάζουμε τις αντοχές για να απορρίψουμε τις μεγάλες διαφορές. Διότι κατά την πρώτηανάγνωση, κάθε φορά που διαβαζόταν η αντοχή και τοποθετείτο στη μεταβλητή F, η προηγούμενητιμή της F χανόταν.Η πρόσθετη δεύτερη ανάγνωση, καθυστερεί το πρόγραμμα (ανάγνωση από το δίσκο είναι της τάξηςτων msec). Θα θέλαμε κάποιο τρόπο να έχουμε μαζικές μεταβλητές που να κρατάνε όλες τιςαντοχές στη μνήμη. Για αυτό η Fortran (και όλες οι γλώσσες προγραμματισμού) έχουν την έννοιατου μητρώου ή πίνακα, που μπορεί να αντιστοιχεί σε χιλιάδες μεταβλητές. Ένα μητρώο είναι μίασυλλογή από πολλές μεταβλητές με ίδιο όνομα (και τύπο), που διακρίνονται μεταξύ τους από ένανακέραιο, που λέγεται δείκτης, ο οποίος λαμβάνει τιμές 1,2,3,4,...., M. M είναι η διάσταση τουμητρώου που πρέπει αν είναι σταθερά, και ορίζεται στην εντολή:

DIMENSION A(1000) ! M=1000Η παραπάνω εντολή ορίζει 1000 μεταβλητές τις:

A(1), A(2), A(3), ..., A(999), A(1000)Προσοχή, ο δείκτης δεν παίρνει την τιμή 0 όπως για παράδειγμα στη γλώσσα προγραμματισμού C.Επίσης ο δείκτης πρέπει να είναι σε παρενθέσεις και όχι σε αγκύλες:

A[0], A[1], A[2], ..., A[998], A[999] !ΛάθοςΕπίσης οι μεταβλητές

A1, A2, A3είναι τελείως διαφορετικές από τις

A(1), A(2), A(3)

Η κάθε μία από τις μεταβλητές (που λέγεται και στοιχείο του πίνακα), μπορεί να έχει διαφορετικήτιμή από τις άλλες και δεν χάνει την τιμή της όταν σε κάποια άλλη θέτουμε μία τιμή: A(23) = 3.1415 A(203) = -1.0 ! Η A(23) παραμένει 3.1414 A(1) = 0.1 ! Η A(23) παραμένει 3.1414 και η A(203) παραμένει -1.0 A(23) = 0.0 ! Η A(203) παραμένει -1.0 και η A(1) παραμένει 0.1Είναι μεγάλο λάθος να γράψουμε F χωρίς δείκτη όταν έχουμε δηλώσει ότι το F είναι μητρώο σεDIMENSION (θα δούμε εξαιρέσεις σε αυτόν το κανόνα παρακάτω). Ποια μεταβλητή από τις 1000εννοούμε;Επίσης, όπως στην γλώσσα C, αλλά σε αντίθεση με τη γλώσσα BASIC, δεν επιτρέπεται να έχουμεένα μητρώο F και μία μεταβλητή F, έτσι ώστε η F να είναι διαφορετική από οποιαδήποτεμεταβλητή F(I).

Συνεπώς, στο προηγούμενο παράδειγμα αν οι αντοχές τοποθετηθούν σε ένα μητρώο, δεν χρειάζεταινα ξαναδιαβαστούν, αφού οι μεταβλητές (τα στοιχεία) του μητρώου δεν χάνουν τις τιμές τους. Έτσιο κώδικας γίνεται:

program skyr implicit none integer :: n, i, m

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 78

Page 79: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

real :: sum, fmes real, dimension(1000) :: f open (11, file='skyr.txt', status='old') read (11, '(i3)') n if (n > 1000) stop 'Μέχρι 1000 δοκίμια' sum = 0.0 do i=1, n read (11, '(f10.0)') f(i) sum = sum + f(i) end do fmes = sum/real(n) write (*, '(a, f10.1)') 'ΜΕΣΟΣ ΟΡΟΣ=', fmes m = 0 sum = 0.0 do i=1, n if (abs(f(i)-fmes) < 5.0) then sum = sum + f(i) m = m + 1 else write (*, '(a, f10.1, a)') 'ΤΟ ΔΟΚΙΜΙΟ ΜΕ ΑΝΤΟΧΗ', f(i), & ' ΑΠΟΡΡΙΠΤΕΤΑΙ' end if end do fmes = sum/real(m) write (*, '(a, f10.1)') 'ΜΕΣΟΣ ΟΡΟΣ=', fmes close (11)end program skyr

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 79

Page 80: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Δευτέρα 7/7/2014 10:45-14:30, B' πολ. Μηχανικών, Προγραμματισμός Η/Υ, θεωρία, Α Τμήμα (01AB) Ονοματισμένες σταθερές και εύρεση ελαχίστου με πίνακεςΠαράδειγμαΣε αρχείο a.mhk είναι γραμμένα τα στοιχεία των πασσάλων (σημείων) μηκοτομής οδού. Σε κάθεσειρά το όνομα apas (με 10 θέσεις), η Χ.Θ. xth, και το υψόμετρο εδάφους yed (με 10 θέσεις και 2δεκαδικά. Να υπολογιστεί και να τυπωθεί το ελάχιστο υψόμετρο ymin, καθώς και το όνομαπασσάλου, τη Χ.Θ. Και τη σειρά του αρχείου που αντιστοιχεί σε αυτό. Να υπολογιστεί τουψόμετρο της ερυθράς yer (τελικό υψόμετρο οδού), θεωρώντας οδό με μηδενική κλίση καιισοσκελισμό εκσκαφών και επιχώσεων (δηλαδή το μέσο όρο των υψομέτρων). Στη συνέχεια ναυπολογιστεί το ύψος επίχωσης ή το βάθος εκσκαφής σε κάθε πάσσαλο dy = yed-yer και να τυπωθείμαζί με το όνομα πασσάλου, τη Χ.Θ., το υψόμετρο εδάφους και το υψόμετρο ερυθράς.

Θα αποθηκεύσουμε το όνομα πασσάλου, Χ.Θ και υψόμετρο εδάφους σε μητρώα, έτσι ώστε τοapas(i), xth(i), και yed(i) να αντιστιχούν στο ίδιο πάσσαλο (που διαβάστηκε από τη γραμμή i τουαρχείου). Τα μητρώα αυτά λέγονται και παράλληλα μητρώα, και παίρνουν το όνομά τους επειδή αντα γράψουμε υπό μορφή πίνακα είναι σε μορφή “παράλληλων” στηλών.

Στοιχείο πίνακα aPas xth yed

1 Π1 0.0 67.38

2 Π2 18.00 67.26

3 Π3 36.63 67.42

Κώδικας:

program mhk1 implicit none integer :: i, nPas, ierr, imin real, dimension(1000) :: xth, yed real :: yedmin, xthmin, yer, s character(len=10), dimension(1000) :: apas character(len=10) :: apasmin open (11, file='a.mhk', status='old') open (12, file='a.ery', status='new') do i=1, 1000 read (11, '(a, 2f10.0)', iostat=ierr) apas(i), xth(i), yed(i) if (ierr > 0) then write (*, *) 'Syntax error at line ', i stop end if if (ierr < 0) exit end do if (ierr == 0) then write (*, *) 'Μέχρι 1000 πασσάλους' stop end if nPas = i - 1 imin = 1 yedmin = yed(imin)

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 80

Page 81: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

xthmin = xth(imin) apasmin = apas(imin) do i=2, nPas if (yed(i) < yedmin) then imin = i yedmin = yed(imin) xthmin = xth(imin) apasmin = apas(imin) end if end do write (*, '(i5, 3x, a, 2f10.2)') imin, apasmin, xthmin, yedmin s = 0.0 do i=1, nPas s = s + yed(i) end do yer = s / real(nPas) do i=1, nPas write (12, '(a, 4f10.2)') aPas(i), xth(i), yed(i), yer, yed(i)-yer end do close (11) close (12)end program mhk1

Παρατηρήσεις:1. Αν σε κάποια οδό οι πάσσαλοι είναι > 1000 πρέπει να αλλάξουμε το 1000 σε πχ 2000 σε 4 σειρέςτου προγράμματος, με αποτέλεσμα να μπορεί να παραληφθεί κάποια από απροσεξία. Θα θέλαμε ναμπορούσαμε να θέταμε το 1000 σε μια μεταβλητή, για παράδειγμα MPAS, και μετά ναχρησιμοποιούμε αυτή όπου υπάρχει το 1000. Αλλά αυτό δεν γίνεται διότι α) η δήλωση τωνμεταβλητών και μητρώων προηγούνται από οποιαδήποτε ανάθεση μεταβλητής, β) η υποεντολήDIMENSION απαιτεί σταθερά (όχι μεταβλητή). Η λύση στη Fortran είναι οι ονοματισμένεςσταθερές (named constants) που είναι ειδικές μεταβλητές που παίρνουν τιμή κατά τη δήλωσή τους,και δεν επιτρέπεται να αλλάξει η τιμή τους στο πρόγραμμα. Δηλώνονται με την υποεντολήPARAMETER: INTEGER, PARAMETER :: MPAS=1000Οι ονοματισμένες σταθερές επιτρέπονται σε DIMENSION και οπουδήποτε αλλού χρειάζεται μίασταθερά.2. Επειδή χρειάζεται το ελάχιστο υψόμετρο εδάφους και επίσης η Χ.Θ. και το όνομα πασσάλου,είναι απαραίτητο να αποθηκεύονται και αυτά μαζί με το ελάχιστο υψόμετρο, το οποίο περιπλέκειτον κώδικα. Εναλλακτικά, θα μπορούσε να βρεθεί η θέση του ελαχίστου στο μητρώο (δηλαδή οδείκτης imin του μητρώου yed, έτσι ώστε yed(imin) να είναι το ελάχιστο υψόμετρο.Με αυτές τις αλλαγές ο κώδικας γίνεται:

program mhk2 implicit none integer, parameter :: MPAS=1000 integer :: i, nPas, ierr, imin real, dimension(MPAS) :: xth, yed real :: yer, s character(len=10), dimension(MPAS) :: apas open (11, file='a.mhk', status='old')

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 81

Page 82: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

open (12, file='a.ery', status='new') do i=1, MPAS read (11, '(a, 2f10.0)', iostat=ierr) apas(i), xth(i), yed(i) if (ierr > 0) then write (*, *) 'Syntax error at line ', i stop end if if (ierr < 0) exit end do if (ierr == 0) then write (*, *) 'Μέχρι ', MPAS, ' πασσάλους' stop end if nPas = i - 1 imin = 1 do i=2, nPas if (yed(i) < yed(imin)) imin = i end do write (*, '(i5, 3x, a, 2f10.2)') imin, apas(imin), xth(imin),yed(imin) s = 0.0 do i=1, nPas s = s + yed(i) end do yer = s / real(nPas) do i=1, nPas write (12, '(a, 4f10.2)') aPas(i), xth(i), yed(i), yer, yed(i)-yer end do close (11) close (12)end program mhk2

Μητρώα και υποπρογράμματαΌταν ένα μητρώο είναι εικονική παράμετρος σε υποπρόγραμμα (dummy argument), εκτός από τηδήλωση του τύπου (ακέραιο, πραγματικό κλπ) πρέπει να δηλωθεί και η διάσταση του μητρώου:

SUBROUTINE MMM (A, B)REAL, DIMENSION(100) :: A, B

Η διάσταση του μητρώου πρέπει να συμφωνεί με αυτή του μητρώου στο κύριο πρόγραμμα:

PROGRAM XXXREAL, DIMENSION(100) :: C, DCALL MMM (C, D)

Εναλλακτικά μπορούμε να δώσουμε στο υποπρόγραμμα την ειδική διάσταση : (άνω και κάτωτελεία). Σε αυτή την περίπτωση ο μεταγλωττιστής συμπληρώνει μόνος του τη διάσταση τουμητρώου, έτσι ώστε να συμφωνεί με αυτή στο κύριο πρόγραμμα:SUBROUTINE MMM (A, B)REAL, DIMENSION(:) :: A, B

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 82

Page 83: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Η άνω και κάτω τελεία επιτρέπεται μόνο σε μητρώα που είναι εικονικές παράμετροι (και επίσης σεμητρώα allocatable). Επίσης πρέπει υποχρεωτικά το υποπρόγραμμα να είναι σε module.

ΠαράδειγμαΣρτο αρχείο SKYR.TXT είναι γραμμένες αντοχές δοκιμίων μία σε κάθε σειρά. Να βρείτε την τιμήκαι τη θέση της ελάχιστης αντοχής χρησιμοποιώντας υποπρογράμματα. Επίσης τη θέση και τηντιμή της αντοχής που βρίσκεται πιο κοντά στο μέσο όρο.

module modskyrimplicit none

contains

subroutine redok (f, nf, mf) real, dimension(:), intent(out) :: f integer, intent(out) :: nf integer, intent(in) :: mf integer :: i, ierr do i=1, mf read (11, *, iostat=ierr) f(i) if (ierr < 0) exit if (ierr > 0) stop 'Συντακτικό λάθος' end do if (ierr == 0) then write (*, *) 'Μέχρι ', mf, ' δοκίμια' stop end if nf = i - 1end subroutine redok

real function aveg(x, n) real, dimension(:), intent(in) :: x integer, intent(in) :: n integer :: i real :: sum sum = 0.0 do i=1, n sum = sum + x(i) end do aveg = sum/real(n)end function aveg

integer function jmin(u, n) real, dimension(:), intent(in) :: u integer, intent(in) :: n integer :: i jmin = 1 do i=2, n if (u(i) < u(jmin)) jmin = i end doend function jmin

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 83

Page 84: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

integer function jav(u, n, umes) real, dimension(:), intent(in) :: u integer, intent(in) :: n real, intent(in) :: umes integer :: i jav = 1 do i=2, n if (abs(u(i)-umes) < abs(u(jav)-umes)) jav = i end doend function jav

end module modskyr

program skyr1 use modskyr implicit none integer, parameter :: MDOK=100 real, dimension(MDOK) :: f integer :: nDok, im real :: fmes open (11, file='skyr.txt', status='old') call redok (f, nDok, MDOK) fmes = aveg(f, nDok) write (*, *) 'ΜΕΣΟΣ ΟΡΟΣ=', fmes im = jmin(f, nDok) write (*, *) 'min ΑΝΤΟΧΗ: ', f(im), ' ΣΤΗ ΘΕΣΗ: ', im im = jav(f, nDok, fmes) write (*, *) 'ΚΟΝΤΑ ΣΤΗ ΜΕΣΗ ΑΝΤΟΧΗ: ', f(im), ' ΣΤΗ ΘΕΣΗ: ', im close (11)end program skyr1

Επειδή μετά το THEN έχω μόνο μία εντολή, μπορώ να χρησιμοποιήσω το συντομογραφία: if (u(i) < u(jmin)) jmin = iτο οποίο οδηγεί σε πιο ευανάγνωστο κώδικα.

ΠαράδειγμαΣτο προηγούμενο παράδειγμα, μετατρέψτε τη συνάρτηση jmin σε υπορουτίνα, η οποία θα βρίσκειτην θέση της ελάχιστης αντοχής και θα την αντιμεταθέτει με αυτή που βρίσκεται στην πρώτη θέσητου μητρώου.

subroutine jmin(u, n) real, dimension(:), intent(inout) :: u integer, intent(in) :: n integer :: i, jm real :: t jm = 1 do i=2, n if (u(i) < u(jm)) jm = i end do t = u(1)

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 84

Page 85: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

u(1) = u(jm) u(jm) = tend subroutine jmin

program skyr2 use modskyr implicit none integer, parameter :: MDOK=100 real, dimension(MDOK) :: f integer :: nDok, im real :: fmes open (11, file='skyr.txt', status='old') call redok (f, nDok, MDOK) fmes = aveg(f, nDok) write (*, *) 'ΜΕΣΟΣ ΟΡΟΣ=', fmes call jmin(f, nDok) write (*, *) 'min ΑΝΤΟΧΗ: ', f(1), ' ΣΤΗ ΘΕΣΗ: ', 1 im = jav(f, nDok, fmes) write (*, *) 'ΚΟΝΤΑ ΣΤΗ ΜΕΣΗ ΑΝΤΟΧΗ: ', f(im), ' ΣΤΗ ΘΕΣΗ: ', im close (11)end program skyr2

Στην αίθουσα να γίνει πίνακας με τις τιμές των μεταβλητών κατά την αντιμετάθεση.

Άσκηση ταξινόμησηςΣε αρχείο A.TXT στην πρώτη σειρά είναι γραμμένο πλήθος αριθμών (μέχρι 1000). Στις επόμενεςείναι οι πραγματικοί αριθμοί. Να γίνει ταξινόμηση κατά αύξουσα σειρά και να τυπωθούν και νατυπωθεί και η διάμεσος των αριθμών, η οποία για λόγους ευκολίας θεωρείται ως η iοστόςμικρότερος αριθμός όπου i = πλήθος αριθμών / 2 με αποκοπή δεκαδικών.

Βασικά βρίσκουμε το ελάχιστο ενός μέρους του πίνακα πολλές φορές.

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 85

Page 86: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 86

Page 87: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

module modutilimplicit nonecontains

subroutine stopmax(m, ames) integer, intent(in) :: m character(len=*), intent(in) :: ames write (*, *) 'Μέχρι ', m, ' ', ames stopend subroutine stopmaxend module modutil

program taxin use modutil implicit none integer, parameter :: MF=1000 integer :: i, j, nf, im real, dimension(MF) :: f real :: temp open (11, file='a.txt', status='old') read (11, *) nf if (nf > MF) call stopmax(MF, 'αριθμοί') do i=1, nf read (11, *) f(i) end do do j=1, nf-1 im = j do i=j+1, nf if (f(i) .lt. f(im)) im = i end do temp = f(j) f(j) = f(im) f(im) = temp end do do i=1, nf write (*, *) f(i) end do write (*, *) 'Διάμεσος:', f(nf/2) !Προσοχή:ακέραια διαίρεση close (11)end program taxin

Στην αίθουσα να γίνει πίνακας με τις τιμές του μητρώου.

5 IM=1-> 2->2->2->2 -1 -1-1 5 IM=2->2->4->5 07 7 72 2 20 0 5

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 87

Page 88: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

-1 -10 07 IM=3->4->4 22 75 5

-1 -10 02 27 IM=4->5 55 7

Άσκηση (παλιό θέμα)Γράψτε το διάγραμμα ροής και το αντίστοιχο πρόγραμμα σε Fortran το οποίο να υπολογίζει το 4ομεγαλύτερο όρο της ακολουθίας:

bn = sin(n2 / 1000)για n=1 έως 100.

(βαθμ. 3.0)

Θα γίνει φθίνουσα ταξινόμηση και θα τυπωθεί το 4ο στοιχείο.

program sin4 implicit none integer, parameter :: MB=100 real, dimension(MB) :: b integer :: i, j, imax real :: t do i=1, MB b(i) = sin(real(i)**2/1000.0) end do do j=1, MB-1 imax = j do i=j+1, MB if (b(i) > b(imax)) imax = i end do t = b(j) b(j) = b(imax) b(imax) = t end do write (*, *) b(4) stopend program sin4

Παράλληλα μητρώα - παράλληλη ταξινόμησηΑρκετές φορές χρειάζονται περισσότερες από μία ετερογενείς πληροφορίες (ή ιδιότητες) για κάθεαντικείμενο. Για παράδειγμα ο βαθμός και το όνομα ενός φοιτητή. Η αντοχή και ο χρόνοςσκλήρυνσης ενός δοκιμίου. Η περιγραφή, η μονάδα και η τιμή μονάδος οικοδομικών υλικών (άλλαυλικά πωλούνται με το κιλό άλλα με το τετραγωνικό μέτρο κλπ.). Η αποθήκευση πολλών ιδιοτήτωνγίνονται με “παράλληλα” μητρώα. Για παράδειγμα το μητρώο BAT(J) αποθηκεύει το βαθμό του

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 88

Page 89: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

φοιτητή j και το μητρώο EPON(J) αποθηκεύει το επώνυμο του ίδιου φοιτητή:

J KOD EPON(J) BAT(J)

1 373 ΣΤΑΜΟΣ 5.5

2 787 ΓΙΑΝΝΟΠΟΥΛΟΣ 6.5

3 123 ΠΑΠΑΔΟΠΟΥΛΟΣ 8.0

Παρατηρούμε ότι έτσι όπως είναι γραμμένα τα στοιχεία των μητρώων στον παραπάνω πίνακαφαίνονται “παράλληλα”.Ένα συνηθισμένο λάθος που γίνεται όταν έχουμε πολλές ιδιότητες για κάθε αντικείμενο είναι ναμεταβάλλουμε μόνο τη μία ιδιότητα ενός αντικειμένου όταν στην πραγματικότητα πρέπει ναμεταβάλλουμε όλες τις ιδιότητές του. Για παράδειγμα αν ο 3ος φοιτητής δεν είναι ο Παπαδόπουλος(έχει γράψει άλλο μάθημα) αλλά ο Βγενόπουλος, η παρακάτω μεταβολή είναι λανθασμένη:

EPON(3) = 'ΒΓΕΝΟΠΟΥΛΟΣ'

γιατί παραμένει ο βαθμός του Παπαδόπουλου. Ο σωστός τρόπος είναι να μεταβάλλουμε όλα ταπαράλληλα μητρώα:

EPON(3) = 'ΒΓΕΝΟΠΟΥΛΟΣ' BAT(3) = 9.5

Κλασσικό παράδειγμα μεταβολής είναι η ταξινόμηση παράλληλων πινάκων με βάση μία ιδιότητα.

ΠαράδειγμαΣε κάθε γραμμή αρχείου BAT.TXT είναι γραμμένο το όνομα φοιτητής με 20 θέσεις και ο βαθμόςτου με 5 θέσεις (ως πραγματικός αριθμός). Να τυπωθεί σε αρχείο 'TAKS.TXT' οι ίδιες πληροφορίεςταξινομημένες κατά το όνομα.

module modutilimplicit nonecontains

subroutine stopmax(m, ames) integer, intent(in) :: m character(len=*), intent(in) :: ames write (*, *) 'Μέχρι ', m, ' ', ames stopend subroutine stopmax

subroutine stopSyntax(m, afn) integer, intent(in) :: m character(len=*), intent(in) :: afn write (*, *) 'Στνατικό λάθος στη γραμμή ', m, ' του αρχείου ', afn stopend subroutine stopSyntax

end module modutil

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 89

Page 90: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

program taxbat1 use modutil implicit none integer, parameter :: MFOIT=2000 integer, dimension(MFOIT) :: kod real, dimension(MFOIT) :: bat character(len=20), dimension(MFOIT) :: epon integer :: i, j, nFoit, ier, im character(len=20) :: atemp

open (11, file='bat.txt', status='old') open (12, file='taks.txt', status='new') do i=1, MFOIT read (11, '(i10, a20, f5.0)', iostat=ier) kod(i), epon(i), bat(i) if (ier < 0) exit if (ier > 0) call stopSyntax(i, 'bat.txt') end do if (ier == 0) call stopmax (MFOIT, 'φοιτητές') nFoit = i - 1

do j=1, nFoit-1 im = j do i=j+1, nFoit if (epon(i) < epon(im)) im = i end do atemp = epon(j) epon(j) = epon(im) epon(im) = atemp end do do i=1, nFoit write (12, '(i10, a20, f5.1)') kod(i), epon(i), bat(i) end do close (11) close (12)end program taxbat1

Ο παραπάνω κώδικας είναι λανθασμένος γιατί δεν μεταβάλλει ανάλογα τους κωδικούς και τουςβαθμούς. Τα αποτελέσματα του προγράμματος είναι:

J KOD EPON(J) BAT(J)

1 373 ΓΙΑΝΝΟΠΟΥΛΟΣ 5.5

2 787 ΠΑΠΑΔΟΠΟΥΛΟΣ 6.5

3 123 ΣΤΑΜΟΣ 8.0

που είναι βέβαια λανθασμένα. Ο σωστός κώδικας είναι (με μετατροπή σε Fortran95):

module modutilimplicit nonecontains

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 90

Page 91: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

subroutine stopmax(m, ames) integer, intent(in) :: m character(len=*), intent(in) :: ames write (*, *) 'Μέχρι ', m, ' ', ames stopend subroutine stopmax

subroutine stopSyntax(m, afn) integer, intent(in) :: m character(len=*), intent(in) :: afn write (*, *) 'Στνατικό λάθος στη γραμμή ', m, ' του αρχείου ', afn stopend subroutine stopSyntax

end module modutil

program taxbat2 use modutil implicit none integer, parameter :: MFOIT=2000 integer, dimension(MFOIT) :: kod real, dimension(MFOIT) :: bat character(len=20), dimension(MFOIT) :: epon integer :: i, j, nFoit, ier, im real :: temp character(len=20) :: atemp

open (11, file='bat.txt', status='old') open (12, file='taks.txt', status='new') do i=1, MFOIT read (11, '(i10, a20, f5.0)', iostat=ier) kod(i), epon(i), bat(i) if (ier < 0) exit if (ier > 0) call stopSyntax(i, 'bat.txt') end do if (ier == 0) call stopmax (MFOIT, 'φοιτητές') nFoit = i - 1

do j=1, nFoit-1 im = j do i=j+1, nFoit if (epon(i) < epon(im)) im = i end do atemp = epon(j) epon(j) = epon(im) epon(im) = atemp ier = kod(j) kod(j) = kod(im) kod(im) = ier temp = bat(j) bat(j) = bat(im)

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 91

Page 92: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

bat(im) = temp end do do i=1, nFoit write (12, '(i10, a20, f5.1)') kod(i), epon(i), bat(i) end do close (11) close (12)end program taxbat2

J KOD EPON(J) BAT(J)

2 787 ΓΙΑΝΝΟΠΟΥΛΟΣ 6.5

3 123 ΠΑΠΑΔΟΠΟΥΛΟΣ 8.0

1 373 ΣΤΑΜΟΣ 5.5

ΠαράδειγμαΣτο αρχείο A.TXT έχουν γραφεί οι αντοχές δοκιμίων που λήφθησαν από μία παρτίδασκυροδέματος, μία σε κάθε σειρά. Να υπολογιστεί και να εκτυπωθεί με ένα δεκαδικό στην οθόνη ημέση αντοχή fm, η τυπική απόκλιση σ των δοκιμίων και η χαρακτηριστική αντοχή τουσκυροδέματος fck=fm-1,64σ. Στη συνέχεια να γίνει το ίδιο για άλλες 2 παρτίδες σκυροδέματος στααρχεία B.TXT και C.TXT. Να μην χρησιμοποιηθούν υποπρογράμματα

Με πίνακες ο κώδικας γίνεται:

module modutilimplicit nonecontains

subroutine stopmax(m, ames) integer, intent(in) :: m character(len=*), intent(in) :: ames write (*, *) 'Μέχρι ', m, ' ', ames stopend subroutine stopmax

subroutine stopSyntax(m, afn) integer, intent(in) :: m character(len=*), intent(in) :: afn write (*, *) 'Στνατικό λάθος στη γραμμή ', m, ' του αρχείου ', afn stopend subroutine stopSyntax

end module modutil

program tria use modutil implicit none

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 92

Page 93: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

integer, parameter :: MFIL=3, MDOK=200 character(len=10), dimension(MFIL) :: afn real, dimension(MDOK) :: f integer :: nDok, i, j, ifil real :: sum, fm, s, fyk afn(1) = 'a.txt' afn(2) = 'b.txt' afn(3) = 'c.txt'

do ifil=1, MFIL open (11, file=afn(ifil), status='old') sum = 0.0 do i=1, MDOK read (11, *, iostat=j) f(i) if (j < 0) exit if (j > 0) call stopSyntax(i, afn(ifil)) sum = sum + f(i) end do if (j == 0) call stopmax(MDOK, 'δοκίμια') nDok = i - 1 fm = sum / real(nDok) sum = 0.0 do i=1, nDok sum = sum + (f(i)-fm)**2 end do s = sqrt(sum/real(nDok)) fyk = fm - 1.64*s write (*, '(a20, f10.1, f10.1, f10.1)') afn(ifil), fm, s, fyk close (11) end doend program tria

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 93

Page 94: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Παρασκευή 11/7/2014 11:45-15:30, B' πολ. Μηχανικών, Προγραμματισμός Η/Υ, θεωρία, Β Τμήμα (03ΑΒ)

ΆσκησηΣε αρχείο είναι γραμμένο καρδιογράφημα με τη μορφή ζευγών χρόνου-έντασης. Σε κάθε σειρά τουαρχείου έχει γραφεί ο χρόνος και η τιμή της έντασης με FORMAT F5.1, F10.1. Στη τελευταία σειράτου αρχείου έχουν γραφεί αρνητικές τιμές. Να γραφεί πρόγραμμα σε Fortran το οποίο, αφούδιαβάσει τα δεδομένα:α. Να υπολογίζει και να τυπώνει τη μέση ένταση AV όλου του καρδιογραφήματος.β. Να βρίσκει και να τυπώνει τις 3 μεγαλύτερες εντάσεις και το χρόνο στον οποίο συμβαίνουν.γ. Να βρίσκει και να τυπώνει τις 3 μικρότερες εντάσεις και το χρόνο στον οποίο συμβαίνουν.δ. Να υπολογίζει το μέσο όρο AVMAX των 3 μεγαλύτερων εντάσεων και το μέσο όρο AVMIN των3 μικρότερων εντάσεων.ε. Αν η διαφορά μεταξύ AVMAX και AV είναι ίση με τη διαφορά μεταξύ AVMIN και AV (με ανοχή±10), να τυπώνει “ΕΝΤΑΞΕΙ”. Αλλιώς να τυπώνει “ΧΡΕΙΑΖΟΝΤΑΙ ΚΑΙ ΑΛΛΕΣ ΕΞΕΤΑΣΕΙΣ”.Σημείωση: Τα FORMAT εκτύπωσης θα είναι ανάλογα με τα FORMAT ανάγνωσης.

program kar1 implicit none integer, parameter :: MKAR=1000 real, dimension(MKAR) :: t, e integer :: i, j, im, nKar real :: sum, temp, av, avmin, avmax open (11, file='kar.txt', status='old') sum = 0.0 do i=1, MKAR j = i read (11, '(f5.0, f10.0)') t(i), e(i) sum = sum + e(i) !ΛΑΘΟΣ: ΠΡΟΣΘΕΤΟΥΜΕ ΚΑΙ ΑΡΝΗΤΙΚΕΣ ΤΙΜΕΣ if (t(i) < 0.0) exit end do if (t(j) >= 0.0) then write (*, *)'ΜΕΧΡΙ ', MKAR, ' ΖΕΥΓΗ' stop end if nKar = i - 1 av = sum/real(nKar) write (*, '(a, f10.1)') 'ΜΕΣΗ ΤΙΜΗ ΕΝΤΑΣΗΣ=', av do j=1, nKar-1 im = j do i=j+1, nKar if (e(i) < e(im)) im = i end do temp = e(j) e(j) = e(im) e(im) = temp end do !ΛΑΘΟΣ: ΔΕΝ ΑΝΤΙΜΕΤΑΘΕΣΑΜΕ t(i) sum = 0.0 write (*, *) 'ΤΡΕΙΣ ΜΙΚΡΟΤΕΡΕΣ ΕΝΤΑΣΕΙΣ' do i=1, 3 write (*, '(f5.1, f10.1)') t(i), e(i)

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 94

Page 95: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

sum = sum + e(i) end do avmin = sum/3.0 write (*, '(a, f10.1)') 'ΜΕΣΗ ΕΛΑΧΙΣΤΩΝ=', avmin! sum = 0.0 !ΛΑΘΟΣ: ΔΕΝ ΜΗΔΕΝΙΣΑΜΕ sum write (*, *) 'ΤΡΕΙΣ ΜΕΓΑΛΥΤΕΡΕΣ ΕΝΤΑΣΕΙΣ' do i=nKar-3, nKar !ΛΑΘΟΣ: ΠΑΙΡΝΟΥΜΕ 4 ΜΕΓΑΛΥΤΕΡΕΣ ΤΙΜΕΣ write (*, '(f5.1, f10.1)') t(i), e(i) sum = sum + e(i) end do avmax = sum/3.0 write (*, '(a, f10.1)') 'ΜΕΣΗ ΜΕΓΙΣΤΩΝ=', avmax if (avmax-av > (avmin-av)+10.0) then !ΛΑΘΟΣ: Ο ΟΡΟΣ ΣΕ ΠΑΡΕΝΘΕΣΗΕΙΝΑΙ ΑΡΝΗΤΙΚΟΣ write (*, *) 'ΧΡΕΙΑΖΟΝΤΑΙ ΚΑΙ ΑΛΛΕΣ ΕΞΕΤΑΣΕΙΣ' else write (*, *) 'ΕΝΤΑΞΕΙ' end if close (11)end program kar1

Διορθώσεις δίνουν:

program kar2 implicit none integer, parameter :: mkar=1000 real, dimension(mkar) :: t, e integer :: i, j, im, nkar real :: sum, temp, av, avmin, avmax open (11, file='kar.txt', status='old') sum = 0.0 do i=1, mkar j = i read (11, '(f5.0, f10.0)') t(i), e(i) if (t(i) < 0.0) exit sum = sum + e(i) end do if (t(j) >= 0.0) then write (*, *)'ΜΕΧΡΙ ', MKAR, ' ΖΕΥΓΗ' stop end if nkar = i - 1 av = sum/real(nkar) write (*, '(a, f10.1)') 'ΜΕΣΗ ΤΙΜΗ ΕΝΤΑΣΗΣ=', av do j=1, nkar-1 im = j do i=j+1, nkar if (e(i) < e(im)) im = i end do temp = e(j) e(j) = e(im)

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 95

Page 96: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

e(im) = temp temp = t(j) t(j) = t(im) t(im) = temp end do sum = 0.0 write (*, *) 'ΤΡΕΙΣ ΜΙΚΡΟΤΕΡΕΣ ΕΝΤΑΣΕΙΣ' do i=1, 3 write (*, '(f5.1, f10.1)') t(i), e(i) sum = sum + e(i) end do avmin = sum/3.0 write (*, '(a, f10.1)') 'ΜΕΣΗ ΕΛΑΧΙΣΤΩΝ=', avmin sum = 0.0 write (*, *) 'ΤΡΕΙΣ ΜΕΓΑΛΥΤΕΡΕΣ ΕΝΤΑΣΕΙΣ' do i=nkar-2, nkar write (*, '(f5.1, f10.1)') t(i), e(i) sum = sum + e(i) end do avmax = sum/3.0 write (*, '(a, f10.1)') 'ΜΕΣΗ ΜΕΓΙΣΤΩΝ=', avmax if (avmax-av > (av-avmin)+10.0) then !ΛΑΘΟΣ: ΜΠΟΡΕΙ ΝΑ ΕΙΝΑΙ ΑΝΑΠΟΔΑ write (*, *) 'ΧΡΕΙΑΖΟΝΤΑΙ ΚΑΙ ΑΛΛΕΣ ΕΞΕΤΑΣΕΙΣ' else write (*, *) 'ΕΝΤΑΞΕΙ' end if close (11)end program kar2 PROGRAM KAR

Περαιτέρω διορθώσεις δίνουν:

program kar3 implicit none integer, parameter :: mkar=1000 real, dimension(mkar) :: t, e integer :: i, j, im, nkar real :: sum, temp, av, avmin, avmax, dmin, dmax open (11, file='kar.txt', status='old') sum = 0.0 do i=1, mkar j = i read (11, '(f5.0, f10.0)') t(i), e(i) if (t(i) < 0.0) exit sum = sum + e(i) end do if (t(j) >= 0.0) then write (*, *)'ΜΕΧΡΙ ', MKAR, ' ΖΕΥΓΗ' stop end if nkar = i - 1 av = sum/real(nkar) write (*, '(a, f10.1)') 'ΜΕΣΗ ΤΙΜΗ ΕΝΤΑΣΗΣ=', av do j=1, nkar-1

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 96

Page 97: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

im = j do i=j+1, nkar if (e(i) .lt. e(im)) im = i end do temp = e(j) e(j) = e(im) e(im) = temp temp = t(j) t(j) = t(im) t(im) = temp end do sum = 0.0 write (*, *) 'ΤΡΕΙΣ ΜΙΚΡΟΤΕΡΕΣ ΕΝΤΑΣΕΙΣ' do i=1, 3 write (*, '(f5.1, f10.1)') t(i), e(i) sum = sum + e(i) end do avmin = sum/3.0 write (*, '(a, f10.1)') 'ΜΕΣΗ ΕΛΑΧΙΣΤΩΝ=', avmin sum = 0.0 write (*, *) 'ΤΡΕΙΣ ΜΕΓΑΛΥΤΕΡΕΣ ΕΝΤΑΣΕΙΣ' do i=nkar-2, nkar write (*, '(f5.1, f10.1)') t(i), e(i) sum = sum + e(i) end do avmax = sum/3.0 write (*, '(a, f10.1)') 'ΜΕΣΗ ΜΕΓΙΣΤΩΝ=', avmax dmax = avmax-av dmin = av-avmin if (abs(dmax-dmin) > 10.0) then write (*, *) 'ΧΡΕΙΑΖΟΝΤΑΙ ΚΑΙ ΑΛΛΕΣ ΕΞΕΤΑΣΕΙΣ' else write (*, *) 'ΕΝΤΑΞΕΙ' end if close (11)end program kar3

Ανάγνωση μητρώων από την ίδια σειρά. Έμμεσος βρόχος.

Παράδειγμα με φοιτητές και πολλά μαθήματα.Σε αρχείο bat.txt είναι στην πρώτη σειρά γραμμένοι το πλήθος των φοιτητών N και το πλήθος τωνμαθημάτων M. Σε κάθε μία από τις επόμενες σειρές είναι Μ βαθμοί ενός φοιτητή. Να υπολογιστείο μ.ο. Κάθε φοιτητή, και ο μέσος όρος όλων των μαθημάτων όλων των φοιτητών.

program math1 implicit none integer, parameter :: MMATH=20 real, dimension(MMATH) :: bf integer :: n, m, i real :: sum, sumall open (11, file='bat.txt', status='old') read (11, *) n, m !ΠΡΟΕΙΔΟΠΟΙΗΣΗ: ΔΕΝ ΕΛΕΧΕΤΑΙ ΑΝ > MMATH

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 97

Page 98: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

sumall = 0.0 do i=1, n read (11, *)(bf(i), i=1, m)!ΛΑΘΟΣ:ΜΕΤΑΒΑΛΛΩ ΜΕΤΑΒΛΗΤΗ do sum = 0.0 do i=1, m !ΛΑΘΟΣ:ΜΕΤΑΒΑΛΛΩ ΜΕΤΑΒΛΗΤΗ do sum = sum + bf(i) sumall = sumall + bf(i) end do write (*, *) 'Μ.Ο. ΦΟΙΤΗΤΗ', i, '=', sum/n !ΛΑΘΟΣ:ΜΙΚΤΗ, ΔΙΑΙΡΩΔΙΑ Μ ΚΑΙ ΟΧΙ ΔΙΑ Ν end do write (*, *) 'Μ.Ο. ΟΛΙΚΟΣ =', sumall/(n*m) !ΛΑΘΟΣ:ΜΙΚΤΉ close (11)end program math1

Τα λάθη με m, n πιθανώς οφείλονται στην ονομασία των μεταβλητών που δεν μεταφέρει το τίαποθηκεύουν. Διορθώσεις των σφαλμάτων δίνουν:

program math2 implicit none integer, parameter :: MMATH=20 real, dimension(MMATH) :: bf integer :: nFoit, nMath, i, j real :: sum, sumall open (11, file='bat.txt', status='old') read (11, *) nFoit, nMath if (nMath > MMATH) stop 'Πάρα πολλά μαθήματα' sumall = 0.0 do i=1, nFoit read (11, *)(bf(j), j=1, nMath) sum = 0.0 do j=1, nMath sum = sum + bf(j) sumall = sumall + bf(j) end do write (*, *) 'Μ.Ο. ΦΟΙΤΗΤΗ', i, '=', sum/real(nMath) end do write (*, *) 'Μ.Ο. ΟΛΙΚΟΣ =', sumall/real(nFoit*nMath) close (11)end program math2

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 98

Page 99: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 99

Page 100: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Πολυδιάστατα μητρώα (μέχρι 7 διαστάσεις ) - έννοιες.

ΠαράδειγμαΦοιτητές, πολλά μαθήματα, πολλές σχολές, πολλά πολυτεχνεία, πολλές χώρες, πολλοί πλανήτεςκλπ.

Αναπαράσταση μαθηματικού μητρώου στη Fortran:Έστω το μαθηματικό μητρώο[ 1 -1][ -2 4 ]

α) Το μαθηματικό μητρώο μπορεί να αναπαρασταθεί με βαθμωτές μεταβλητές:A = 1.0 Η ορίζουσα είναι: A*D - B*CB = -1.0C = -2.0D = 4.0

β) Το μητρώο μπορεί να αναπαρασταθεί με μονοδιάστατο μητρώο Fortran (“κατά γραμμές”):REAL, DIMENSION(4) :: X(4)X(1) = 1.0 Η ορίζουσα είναι: X(1)*X(4) - X(3)*X(4)X(2) = -1.0X(3) = -2.0X(4) = 4.0Η αντιστοίχιση μεταξύ του στοιχείου i, j (i=γραμμή, j=στήλη) του μαθηματικού μητρώου και τουστοιχείου k του μητρώου Fortran είναι: K = (I-1)*NSTHL + JΌπου NSTHL=2 ο το πλήθος των στηλών του μαθηματικού μητρώου.

γ) Το μητρώο μπορεί να αναπαρασταθεί με μονοδιάστατο μητρώο Fortran (με διαφορετική διάταξη:“κατά στήλες”):REAL, DIMENSION(4) :: X(4)X(1) = 1.0 Η ορίζουσα είναι: X(1)*X(4) - X(4)*X(3)X(2) = -2.0X(3) = -1.0X(4) = 4.0Η αντιστοίχιση μεταξύ του στοιχείου i, j (i=γραμμή, j=στήλη) του μαθηματικού μητρώου και τουστοιχείου k του μητρώου Fortran είναι: K = (J-1)*NGRAM + IΌπου NGRAM=2 ο το πλήθος των γραμμών του μαθηματικού μητρώου.

δ) Το μητρώο μπορεί να αναπαρασταθεί με διδιάστατο μητρώο Fortran:REAL, DIMENSION(4) :: X(2, 2)X(1, 1) = 1.0 Η ορίζουσα είναι: X(1, 1)*X(2, 2) – X(2, 1)*X(1, 2)X(1, 2) = -2.0X(2, 1) = -1.0X(2, 2) = 4.0

Επειδή η μνήμη του ηλεκτρονικού υπολογιστή είναι από τη φύση της μονοδιάστατη, η Fortran

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 100

Page 101: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

χρησιμοποιεί εσωτερικά την αναπαράσταση γ) (κατά στήλες) για την αναπαράστασηπολυδιάστατων μητρώων, σε αντίθεση με άλλες γλώσσες προγραμματισμού που χρησιμοποιούντην αναπαράσταση β) (κατά γραμμές). Η λεπτομέρεια αυτή δεν επηρεάζει την σύνταξη τωνπρογραμμάτων σε Fortran, εκτός αν απαιτείται συνεργασία με προγράμματα C/C++, και εκεί σεορισμένες περιπτώσεις.

Παράδειγμα με φοιτητές και πολλά μαθήματα.Σε αρχείο bat.txt είναι στην πρώτη σειρά γραμμένοι το πλήθος των φοιτητών N και το πλήθος τωνμαθημάτων M. Σε κάθε μία από τις επόμενες σειρές είναι Μ βαθμοί ενός φοιτητή. Να υπολογιστείο μ.ο. και η τυπική απόκλιση όλων των φοιτητών σε κάθε μάθημα.

module modutilimplicit nonecontains

subroutine stopmax(m, ames) integer, intent(in) :: m character(len=*), intent(in) :: ames write (*, *) 'Μέχρι ', m, ' ', ames stopend subroutine stopmax

subroutine stopSyntax(m, afn) integer, intent(in) :: m character(len=*), intent(in) :: afn write (*, *) 'Στνατικό λάθος στη γραμμή ', m, ' του αρχείου ', afn stopend subroutine stopSyntax

end module modutil

program momath use modutil implicit none integer, parameter :: MFOIT=1000, MMATH=20 real, dimension(MFOIT, MMATH) :: bf integer :: nfoit, nmath, ifoit, imath real :: sum, s, am open (11, file='bat.txt', status='old') read (11, *) nfoit, nmath if (nfoit > MFOIT) call stopmax (MFOIT, 'ΦΟΙΤΗΤΕΣ') if (nmath > MMATH) call stopmax (MMATH, 'ΜΑΘΗΜΑΤΑ') do ifoit=1, nfoit read (11, *) (bf(ifoit, imath), imath=1, nmath) end do

do imath=1, nmath sum = 0.0

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 101

Page 102: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

do ifoit=1, nfoit sum = sum + bf(ifoit, imath) end do am = sum/real(nfoit) write (*, *) 'Μ.Ο. ΜΑΘΗΜΑΤΟΣ', imath, '=', am sum = 0.0 do ifoit=1, nfoit sum = sum + (bf(ifoit, imath)-am)**2 end do s = sqrt(sum/real(nfoit)) write (*, *) 'ΤΥΠΙΚΗ ΑΠΟΚΛΙΣΗ ΜΑΘΗΜΑΤΟΣ', imath, '=', s end do close (11)end program momath

Προσοχή: Οι ονομασίες των μεταβλητών παίζουν σημαντικό ρόλο στη κατανόηση του κώδικα καιαποφυγή λαθών.

Το μέγιστο πλήθος στοιχείων ανά διάσταση είναι (max φοιτητές=1000, max μαθήματα=20) πρέπεινα επιλέγεται με προσοχή. Υπερεκτίμηση του πλήθους μπορεί να οδηγήσει σε μεγάλη σπατάλημνήμης διότι τα πλήιη των διαστάσεων πολλαπλασιάζονται. Για παράδειγμα αν το πλήθος τωνμαθημάτων είναι 10 αντί για 20, τότε έχουμε δεσμεύσει 1000*20 = 20000 στοιχεία αντί για1000*10=10000. Ένας τρόπος να παρακάμψουμε το πρόβλημα είναι να χρησιμοποιήσουμεμητρώα, στα οποία το πλήθος των στοιχείων προσδιορίζεται κατά την εκτέλεση του προγράμματος(runtime) και όχι κατά την μεταγλώττιση (compile time). Ένα τέτοι μητρώο ορίζεται με τηνυποεντολή ALLOCATABALE:PROGRAM TEST3 INTEGER :: N REAL, ALLOCATABLE, DIMENSION(:) :: D !Το μητρώο είναι κενό N = 100 ALLOCATE (D(N)) !Το μητρώο έχει 100 στοιχεία ...Στην αρχή το μητρώο δεν έχει κανένα στοιχείο και δεν δεσμεύει καθόλου μνήμη υπολογιστή. Μετην εντολή ALLOCATE (D(N)) το μητρώο αποκτά N στοιχεία και δεσμεύει τηναπαραίτητη μνήμη. N μπορεί να είναι σταθερά, ή μεταβλητή ή αριθμητικήπαράσταση με σταθερές ή/και μεταβλητές.Είναι δυνατό να αφαιρέσουμε τα στοιχεία αυτού του μητρώου, έτσι ώστε ναέχει πάλι μηδενικά στοιχεία με την εντολή DEALLOCATE και στη συνέχεια νατου δώσουμε διαφορετικό πλήθος στοιχείων. PROGRAM TEST3 INTEGER :: N REAL, ALLOCATABLE, DIMENSION(:) :: D !Το μητρώο είναι κενό N = 100 ALLOCATE (D(N)) !Το μητρώο έχει 100 στοιχεία ... DEALOCATE (D) !Το μητρώο είναι κενό ALLOCATE (D(N**2)) !Το μητρώο έχει 10000 στοιχεία

Τονίζεται ότι με την εντολή DEALLOCATE χάνονται όλες οι τιμές που είχαν τα στοιχεία τουμητρώου και δεν ανακτώνται με την επόμενη ALLOCATE. Επίσης στο τέλος του προγράμματοςδεν απαιτείται να γίνει DEALLOCATE, διότι γίνεται απευθείας από το μεταγλωττιστή (σε αντίθεση

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 102

Page 103: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

με την εντολή OPEN, που μετά απαιτείται η εντολή CLOSE).. Πλεονεκτήματα των μητρώων ALLOCATABLE είναια) Δεν γίνεται σπατάλη μνήμηςβ) σε προβλήματα μαθηματικού ή ηλεκτρολόγου μηχανικού, μερικές φορές δεν είναι γνωστό τομέγιστο πλήθος ενός μητρώου, ούτε κατά προσέγγιση. Πχ το λειτουργικό σύστημα (που είναι καιαυτό πρόγραμμα) δεν μπορεί να γνωρίζει πόση μνήμη θα χρειαστεί ένα πρόγραμμα πριν το τρέξει.Στην επιστήμη του πολιτικού μηχανικού, πάντα γνωρίζουμε το μέγιστο πλήθος ενός μητρώου.Μειονεκτήματα είναι:α) Πιο πολύπλοκη διαδικασίαβ) Αν εκ παραδρομής δεν εκτελεστεί η εντολή ALLOCATE, αυτό οδηγεί σε σφάλματα που είναιδύσκολο να εντοπιστούν και διορθωθούν.γ) Σε παλαιότερους επεξεργαστές της INTEL, AMD κλπ η επεξεργασία των μητρώωνALLOCATABLE είναι σημαντικά πιο αργή, επειδή αποθηκεύονται σε ειδικό μέρος της μνήμης πουλέγεται heap. Νεότεροι επεξεργαστές έχουν λύσει αυτό το πρόβλημα σε μεγάλο βαθμό.δ) Αν τα στοιχεία του μητρώου διαβάζονται από αρχείο και δεν είναι γνωστό το πλήθος των σειρώντου αρχείου, πρέπει να γίνουν 2 αναγνώσεις του αρχείου: Μία για να προσδιοριστεί το πλήθος τωνσειρών, και μία για να διαβαστούν τα στοιχεία του μητρώου.

ΠαράδειγμαΗ προηγούμενη άσκηση με χρήση μητρών ALLOCATABLE γίνεται:

program momath implicit none real, dimension(:, :), allocatable :: bf integer :: nfoit, nmath, ifoit, imath real :: sum, s, am open (11, file='bat.txt', status='old') read (11, *) nfoit, nmath allocate (bf(nfoit, nmath)) do ifoit=1, nfoit read (11, *) (bf(ifoit, imath), imath=1, nmath) end do

do imath=1, nmath sum = 0.0 do ifoit=1, nfoit sum = sum + bf(ifoit, imath) end do am = sum/real(nfoit) write (*, *) 'Μ.Ο. ΜΑΘΗΜΑΤΟΣ', imath, '=', am sum = 0.0 do ifoit=1, nfoit sum = sum + (bf(ifoit, imath)-am)**2 end do s = sqrt(sum/real(nfoit)) write (*, *) 'ΤΥΠΙΚΗ ΑΠΟΚΛΙΣΗ ΜΑΘΗΜΑΤΟΣ', imath, '=', s end do close (11)

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 103

Page 104: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

end program momath

Παράδειγμα:Σε αρχείο D.INP είναι γραμμένες οι διαστάσεις p, q, r δύο μαθηματικών μητρώων [A] μεδιαστάσεις p×q και [B] με διαστάσεις q×r. Στις επόμενες p×q σειρές του αρχείου είναι γραμμένα ταστοιχεία του A, ένα στοιχείο σε κάθε σειρά, και μετά τα q×r στοιχεία του Β, με τον ίδιο τρόπο. Ναυπολογιστεί το μητρωικό γινόμενο [C] = [A] [B] και να γραφεί στο αρχείο D.OUT.

Το γινόμενο των μαθηματικών μητρών είναι μητρώο [C] με διαστάσεις p×r. Κάθε στοιχείο i, j τουμητρώου C είναι:

Cij=∑k=1

q

Aik Bkj

program matmult implicit none integer, parameter :: MM=10 real, dimension(MM, MM) :: a, b, c integer :: i, j, k, ip, iq, ir real :: temp open (11, file='d.inp', status='old') open (12, file='d.out') read (11, *) ip, iq, ir if (ip > MM) stop 'dimension out of bounds' if (iq > MM) stop 'dimension out of bounds' if (ir > MM) stop 'dimension out of bounds'

do i=1, ip do j=1, iq read (11, *) a(i, j) end do end do do i=1, iq do j=1, ir read (11, *) b(i, j) end do end do

do i=1, ip do j=1, ir temp = 0.0 do k=1, iq temp = temp + a(i, k) * b(k, j) end do c(i, j) = temp write (12, *) c(i, j) end do end do close (11) close (12)end program matmult

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 104

Page 105: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Προσοχή: Οι διαστάσεις των μητρώων μπορεί να είναι μικρότερες από 10, 10.

Με μητρώα ALLOCATABLE ο κώδικας γίνεται:

program matmult2 implicit none real, dimension(:, :), allocatable :: a, b, c integer :: i, j, k, ip, iq, ir real :: temp open (11, file='d.inp', status='old') open (12, file='d.out') read (11, *) ip, iq, ir allocate (a(ip, iq), b(iq, ir), c(ip, ir))

do i=1, ip do j=1, iq read (11, *) a(i, j) end do end do do i=1, iq do j=1, ir read (11, *) b(i, j) end do end do

do i=1, ip do j=1, ir temp = 0.0 do k=1, iq temp = temp + a(i, k) * b(k, j) end do c(i, j) = temp write (12, *) c(i, j) end do end do close (11) close (12)end program matmult2

Πολυδιάστατα Μητρώα και υποπρογράμματαΌταν ένα πολυδιάστατο μητρώο είναι εικονική παράμετρος σε υποπρόγραμμα (dummy argument),εκτός από τη δήλωση του τύπου (ακέραιο, πραγματικό κλπ) πρέπει να δηλωθούν και οι διαστάσειςτου μητρώου:

SUBROUTINE MMM (A, B)REAL, DIMENSION(100, 20) :: A, B

Η διάσταση του μητρώου πρέπει να συμφωνεί με αυτή του μητρώου στο κύριο πρόγραμμα:

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 105

Page 106: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

PROGRAM XXXREAL, DIMENSION(100, 20) :: C, DCALL MMM (C, D)

Εναλλακτικά μπορούμε να δώσουμε στο υποπρόγραμμα την ειδική διάσταση : (άνω και κάτωτελεία). Σε αυτή την περίπτωση ο μεταγλωττιστής συμπληρώνει μόνος του τις διαστάσεις τουμητρώου, έτσι ώστε να συμφωνεί με αυτή στο κύριο πρόγραμμα:

SUBROUTINE MMM (A, B)REAL, DIMENSION(:, :) :: A, B

Η άνω και κάτω τελεία επιτρέπεται μόνο σε μητρώα που είναι εικονικές παράμετροι (και επίσης σεμητρώα allocatable). Επίσης πρέπει υποχρεωτικά το υποπρόγραμμα να είναι σε module.

ΠαράδειγμαΝα συντάξετε συνάρτηση ή υπορουτίνα που να τυπώνει διδιάστατο μητρώο με 2 δεκαδικά, και ταστοιχεία μιας γραμμής του μητρώου σε μία σειρά στην οθόνη.

Επειδή η συνάρτηση πρέπει υποχρεωτικά να επιστρέψει μία τιμή, επιστρέφει μία αυθαίρετη πουμπορεί να μπερδέψει όποιον το διαβάζει. Η σωστή λύση είναι να χρησιμοποιηθεί SUBROUTINE:

module modekimplicit nonecontains

subroutine ektyp(a, ngram, nsthl) real, dimension(:, :), intent(in) :: a integer, intent(in) :: ngram, nsthl integer :: i, j do i=1, ngram write (*, '(99f10.2)') (a(i, j), j=1, nsthl) end doend subroutine ektyp

end module modek

program yyy use modek implicit none real, dimension(100, 50) :: b integer :: ngram, nsthl! ... ngram = 20 nsthl = 19 call ektyp (b, ngram, nsthl)end program yyy

Οι ενεργές παράμετροι IN “αντιγράφονται” στις εικονικές όπως λίγο πριν από την εκτέλεση τηςυπορουτίνας, ακριβώς όπως και στην περίπτωση των συναρτήσεων.

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 106

Page 107: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Δευτέρα 14/7/2014 10:45-14:30, B' πολ. Μηχανικών, Προγραμματισμός Η/Υ, θεωρία, Α Τμήμα (01AB)

Παράδειγμα(α) Να γραφεί ένα υποπρόγραμμα το οποίο να υπολογίζει την παροχή Q

Q=1n

bh( bhb+2h )

23 √s

από τις μεταβλητές n, b, s και το βάθος ροής h.(β) Χρησιμοποιώντας το υποπρόγραμμα (α), να γραφεί νέο υποπρόγραμμα που να υπολογίζειζεύγη τιμών h, Q για h=0.0, 0.1, 0.2, 0.3, ...., 9.8, 9.9, 10 και να τα αποθηκεύει σε δύοπαράλληλα μητρώα HP και QP. Τα μητρώα θα έχουν κατάλληλες διαστάσεις. Οι υπόλοιπεςμεταβλητές έχουν τιμές n=0.016, b=2.0, s=0.005(γ) Να γραφεί υποπρόγραμμα το οποίο να δέχεται μία παροχή QX και να βρίσκει τηνκοντινότερη τιμή στο μητρώο QP, έστω QP(I), και να επιστρέφει το αντίστοιχο βάθος HP(I)(δ) Να γραφεί κύριο πρόγραμμα το οποίο να διαβάζει από το πληκτρολόγιο μία παροχή και ναυπολογίζει το βάθος ροής με τη βοήθεια του υποπρογράμματος (γ). Στη συνέχεια να κάνει τοίδιο μέχρι να διαβάσει αρνητική τιμή για την παροχή.

Σε αυτό το παράδειγμα αντί για παράλληλα μητρώο θα χρησιμοποιηθεί ένας διαδιάστατο μητρώοHQ. Το βάθος ροής h θα αντιστοιχεί στα στοιχεία HQ(i, 1) και η παροχή στα στοιχεία HQ(i, 2).Επειδή το υποπρόγραμμα (α) επιστρέφει μόνο μία τιμή, θα χρησιμοποιηθεί συνάρτηση. Για το (β)που υπολογίζει μητρώο θα χρησιμοποιηθεί υπορουτίνα. Για το τρίτο που υπολογίζει μόνο το βάθοςροής θα χρησιμοποιηθεί συνάρτηση.

module modparimplicit nonecontains

real function par(b, h, an, s) real, intent(in) :: b, h, an, s real :: rh rh = (b*h)/(b+2.0*h) par = 1.0/an * b*h * rh**(2.0/3.0) * sqrt(s)end function par

subroutine pinak(hq) real, dimension(:, :), intent(out) :: hq real, parameter :: an=0.016, b=2.0, s=0.005 real :: h integer :: i h = 0.0 do i=1, size(hq, 1) hq(i, 1) = h hq(i, 2) = par(b, h, an, s) write (*, *) i, hq(i, 1), hq(i, 2) h = h + 0.1 end doend subroutine pinak

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 107

Page 108: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

real function bathos(qx, hq) real, dimension(:, :), intent(in) :: hq real, intent(in) :: qx integer :: imin, i imin = 1 do i=2, size(hq, 1) if (abs(qx-hq(i, 2)) < abs(qx-hq(imin, 2))) imin = i end do bathos = hq(imin, 1)end function bathos

end module modpar

program par1 use modpar implicit none real, dimension (101, 2) :: hq real :: qx call pinak (hq) do read (*, *) qx if (qx < 0.0) exit write (*, *) bathos(qx, hq) end doend program par1

Παρατηρείστε ότι έχουμε χρησιμοποιήσει ονοματισμένες σταθερές για το πλάτος του αγωγού, τηνκλίση του αγωγού και του συντελεστή τριβής που είναι σταθερές, αλλά ίσως στο μέλλον θαμπορούσαν να αλλάξουν.Το κύριο πρόγραμμα χρησιμοποιεί τη συνάρτηση bathos για να υπολογίζει το βάθος ροής από τηνπαροχή. Δεν είναι απαραίτητο όταν φτιάχνουμε ένα πρόγραμμα και χρησιμοποιούμε έναυποπρόγραμμα (που πιθανώς έφτιαξε κάποιος άλλος/η) να γνωρίζουμε τις λεπτομέρειες με τιςοποίες το υπορπόγηραμμα υπολογίζει. Αρκεί να γνωρίζουμε ότι χρειάζεται κάποια αρχικοποίηση(initialisation) και στη συνέχεια καλούμε το υποπρόγραμμα. Για αυτό το λόγο, το μητρώο HQπρέπει να τοποθετηθεί στη module. Έτσι ο κώδικας γίνεται:

module modparimplicit noneinteger, parameter :: MHQ=101real, dimension (MHQ, 2) :: hqcontains

real function par(b, h, an, s) real, intent(in) :: b, h, an, s real :: rh rh = (b*h)/(b+2.0*h) par = 1.0/an * b*h * rh**(2.0/3.0) * sqrt(s)end function par

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 108

Page 109: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

subroutine pinak() real, parameter :: an=0.016, b=2.0, s=0.005 real :: h integer :: i h = 0.0 do i=1, size(hq, 1) hq(i, 1) = h hq(i, 2) = par(b, h, an, s) write (*, *) i, hq(i, 1), hq(i, 2) h = h + 0.1 end doend subroutine pinak

real function bathos(qx) real, intent(in) :: qx integer :: imin, i imin = 1 do i=2, size(hq, 1) if (abs(qx-hq(i, 2)) < abs(qx-hq(imin, 2))) imin = i end do bathos = hq(imin, 1)end function bathos

end module modpar

program par2 use modpar implicit none real :: qx call pinak () do read (*, *) qx if (qx < 0.0) exit write (*, *) bathos(qx) end doend program par2

ΠαράδειγμαΣτο προηγούμενο παράδειγμα ο υπολογισμός του βάθους ροής είναι χονδρικός. Να βελτιώσετε τουποπρόγραμμα (γ) να υπολογίζει μεταξύ ποιών στοιχείων του μητρώου QP βρίσκεται η παροχήQX, δηλαδή για ποιο I ισχύει QP(I-1) < QX <= QP(I). Στη συνέχεια με βάση τις QP(I-1), QP(I) νακάνει παρεμβολή μεταξύ των τιμών HP(I-1) και HP(I), για να υπολογίζει και να επιστρέφει το

βάθος ροής για παροχή QX. Ο τύπος της γραμμικής παρεμβολής είναι: y= y1+y2− y1

x2− x1

(x−x1)

Είναι καλύτερα να συντάξουμε ένα υποπρόγραμμα το οποίο κάνει τη γραμμική παρεμβολή.

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 109

Page 110: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

real function gram(x1, y1, x2, y2, x) real, intent(in) :: x1, y1, x2, y2, x gram = y1 + (y2-y1)/(x2-x1) * (x-x1)end function gram

Αν η παροχή QX=0 τότε δεν ισχύει η ανισότητα για κανένα I. Γνωρίζουμε όμως από τον τύπο τηςπαροχής ότι αν QX=0 τότε HX=0. Επίσης αν QX<0 έχει δοθεί λάθος παροχή και αν QX>QP(101)η παροχή είναι τεράστια.

real function bathos(qx) real, intent(in) :: qx integer :: i if (qx < 0.0) then stop 'ΑΡΝΗΤΙΚΗ ΠΑΡΟΧΗ!' else if (qx > hq(size(hq, 1), 2)) then stop 'ΠΟΛΥ ΜΕΓΑΛΗ ΠΑΡΟΧΗ' else if (qx == 0.0) then bathos = 0.0 else do i=2, MHQ if (hq(i, 2) >= qx) exit end do bathos = gram(hq(i-1, 2), hq(i-1, 1), hq(i, 2), hq(i, 1), qx) end ifend function bathos

Ας σημειωθεί ότι έγινε μία πολύ σημαντική αναβάθμιση του προγράμματος αλλάζοντας μόνο τησυνάρτηση BATHOS(). Όλος ο υπόλοιπος κώδικας έμεινε ακριβώς ο ίδιος. Αυτό είναι ένα ακόμαπλεονέκτημα της χρήσης υποπρογραμμάτων. Χωρίζοντας το πρόγραμμα σε υποπρογράμματα ταοποία κάνουν έναν συγκεκριμένο υπολογισμό το καθένα, μπορούμε να αλλάξουμε τελείως έναναπό τους υπολογισμούς (για παράδειγμα αν ανακαλύφθηκε καινούρια μεθοδολογία) χωρίς ναεπηρεάσουμε τους υπόλοιπους υπολογισμούς στο ελάχιστο.

Άσκηση (παλιό θέμα)Σε αρχείο υπάρχουν συντεταγμένες x, y τοπογραφικών σημείων. Σε κάθε σειρά του αρχείουγράφονται οι συντεταγμένες x, y ενός σημείου. Στην τελευταία σειρά του αρχείου υπάρχουν οιαριθμοί 1010 και 1010 (πρέπει να υπάρχουν και οι δύο αριθμοι για να δηλώσουν το τέλος τουαρχείου). Να γραφεί ένα πρόγραμμα που να κάνει τα ακόλουθα:(α) Να διαβάζει τις συντεταγμένες όλων των σημείων.β) Να υπολογίζει και να τυπώνει τις συντεταγμένες του κεντροειδούς σημείου, οι οποίες είναι ομέσος όρος των συντεταγμένων όλων των σημείων.(γ) Να υπολογίζει και να τυπώνει τα 2 κοντινότερα μεταξύ τους σημεία, και τα δύο μακρινότεραμεταξύ τους σημεία. Η απόσταση 2 σημείων μπορεί να υπολογιστεί από το πυθαγόρειο θεώρημα:d=[(x2-x1)2+(y2-y1)2]0.5

(δ) Να ταξινομεί και να τυπώνει τα σημεία σε αύξουσα σειρά απόστασής τους από το κεντροειδές.βαθμ. 5.0)

Οι συντεταγμένες των σημείων, το πλήθος τους N, και οι συντεταγμένες του κεντροειδούςχρειάζονται σχεδόν παντού και τις βάζουμε ως μεταβλητές της module.

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 110

Page 111: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

module modtopimplicit noneinteger, parameter :: MPOINTS=100real, dimension(2, MPOINTS) :: creal, dimension(2) :: cceninteger :: nPointscontains

subroutine readc integer :: i, j real, dimension(2) :: c1 open (11, file='top.in1', status='old') npoints = 0 do read (11, *) (c1(j), j=1, 2) write (*, *) (c1(j), j=1, 2) if (c1(1) >= 1.0e10 .and. c1(2) >= 1.0e10) exit npoints = npoints + 1 if (npoints > mpoints) then write (*, *) 'μέχρι ', mpoints, ' σημεία' stop end if do j=1, 2 c(j, npoints) = c1(j) end do end do close (11)end subroutine readc

subroutine centr integer :: i, j do j=1, 2 ccen(j) = 0.0 end do do i=1, nPoints do j=1, 2 ccen(j) = ccen(j) + c(j, i) end do end do do j=1, 2 ccen(j) = ccen(j) / real(nPoints) end do write (*, *) 'ΚΕΝΤΡΟΕΙΔΕΣ:', (ccen(j), j=1, 2)end subroutine centr

subroutine minmax integer :: imin1, imin2, imax1, imax2, i, j imin1 = 1 imin2 = 2 do i=1, nPoints

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 111

Page 112: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

do j=1, nPoints if (i == j) cycle if (dis(i, j) < dis(imin1, imin2)) then imin1 = i imin2 = j end if end do end do write (*, *) 'ΚΟΝΤΙΝΟΤΕΡΑ ΣΗΜΕΙΑ', (c(j, imin1), j=1, 2), (c(j,imin2), j=1, 2) imax1 = 1 imax2 = 2 do i=1, nPoints do j=1, nPoints if (i == j) cycle if (dis(i, j) > dis(imax1, imax2)) then imax1 = i imax2 = j end if end do end do write (*, *) 'ΜΑΚΡΙΝΟΤΕΡΑ ΣΗΜΕΙΑ', (c(j, imax1), j=1, 2), (c(j,imax2), j=1, 2)end subroutine minmax

subroutine taxin integer :: i, j, k, im real :: t do k=1, nPoints-1 im = k do i=k+1, nPoints if (disc(i) < disc(im)) im = i end do do j=1, 2 t = c(j, k) c(j, k) = c(j, im) c(j, im) = t end do end do do i=1, nPoints write (*, *) (c(j, i), j=1, 2) end doend subroutine taxin

real function disc(i) integer, intent(in) :: i integer :: j disc = 0.0 do j=1, 2 disc = disc + (c(j, i) - ccen(j))**2 end do

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 112

Page 113: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

disc = sqrt(disc)end function disc

real function dis(i, k) integer, intent(in) :: i, k integer :: j dis = 0.0 do j=1, 2 dis = dis + (c(j, k) - c(j, i))**2 end do dis = sqrt(dis)end function dis

end module modtop

program top use modtop implicit none call readc call centr call minmax call taxinend program top

Το πρόγραμμα μπορεί να συνταχθεί και με μητρώα ALLOCATABLE, αλλά θαπρέπει να γίνει αρχικά ανάγνωση των σημείων για να βρεθεί το πλήθος τωνσημείων, και μετά να γίνει ξανά ανάγνωση των αρχείων για να τοποθετηθούνστο μητρώο. Μόνο οι μεταβλητές της module και η υπορουτίνα READCαλλάζουν:

module modtopimplicit nonereal, dimension(:, :), allocatable :: creal, dimension(2) :: cceninteger :: nPointscontains

subroutine readc integer :: i, j real, dimension(2) :: c1 open (11, file='top.in1', status='old') npoints = 0 do read (11, *) (c1(j), j=1, 2) write (*, *) (c1(j), j=1, 2) if (c1(1) >= 1.0e10 .and. c1(2) >= 1.0e10) exit npoints = npoints + 1 end do allocate (c(2, npoints)) rewind (11)

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 113

Page 114: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

do i=1, npoints read (11, *) (c(j, i), j=1, 2) end do close (11)end subroutine readc

Κεφάλαιο 10 – λογικές πράξεις. Στο προηγούμενο πρόγραμμα χρησιμοποιήσαμε τον τελεστή .AND.Προτεραιότητα λογικών πράξεων (.NOT. μετά .AND. μετά .OR.). Να τοποθετούνται ελεύθεραπαρενθέσεις για να αποφεύγονται παρερμηνείες. Άσκηση 10.1. Παραλλαγή της άσκησης 10.1.5:Είτε το I είτε το J βρίσκεται μεταξύ των 1 και 8, αλλά όχι και τα δύο.Λύση 1: IF ((I >= 1 .AND. I <= 8 .AND. .NOT.(J >= 1 .AND. J <= 8)) .OR. & (J >= 1 .AND. J <= 8 .AND. .NOT.(I >= 1 .AND. I <= 8)))Λύση 2: IF ((I >= 1 .AND. I <= 8 .AND. (J < 1 .OR. J > 8)) .OR. & (J >= 1 .AND. J <= 8 .AND. (I < 1 .OR. I > 8)))

Λογικές μεταβλητές – παίρνουν τιμές .TRUE. ή .FALSE. Ισχύουν όσα έχουν ειπωθεί για μικτήαριθμητική. Δηλώνονται ως: LOGICAL INVALD, OK INVALD = .FALSE. OK = .NOT. INVALDΑς σημειωθεί ότι επειδή οι διάφορες λογικές σταθερές ή τελεστές περικλείονται από τελείες δεναποτελούν δεσμευμένες και μπορούν να χρησιμοποιηθούν ως ονόματα μεταβλητών. OR = 3.14 FALSE = 2.718 AND = OR*FALSEΟι λογικές μεταβλητές μπορούν να βοηθήσουν για να απλουστεύσουν και να κάνουν οικονομία σευπολογισμούς. Έτσι το προηγούμενο παράδειγμα γίνεται: LOGICAL LI, LJ LI = I >= 1 .AND. I <= 8 LJ = J >= 1 .AND. J <= 8 IF ((LI .AND. .NOT.LJ) .OR. (LJ .AND. .NOT. LI))

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 114

Page 115: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Δευτέρα 21/7/2014 10:45-14:30, B' πολ. Μηχανικών, Προγραμματισμός Η/Υ, θεωρία, Α Τμήμα (01AB)

Προσοχή: Το πρότυπο της Fortran δεν καθορίζει αν ο υπολογισμός των λογικών πράξεων γίνεταιυπό συνθήκη. Δηλαδή στον παρακάτω κώδικας μπορεί να γίνει διάιρεση δια μηδέν και νασταματήσει το πρόγραμμα με μήνυμα λάθους: X = 0.0 IF (X /= 0.0 .AND. 1.0/X < 1.0) THEN WRITE (*, *) X END IFΟ μεταγλωττιστής πιθανώς υπολογίσει και τις δύο παραστάσεις εκατέρωθεν του τελεστή .AND.και έτσι να γίνει διαίρεση δια μηδέν. Ο σωστός τρόπος είναι ο παρακάτω: X = 0.0 IF (X != 0.0) THEN IF (1.0/X < 1.0) THEN WRITE (*, *) X END IF END IF

ΆσκησηΕυθεία κορυφογραμμή ορίζεται από δύο σημεία Α και Β οι συντεταγμένες XA, YA, HA και HB,YB, HB είναι γραμμένες σε δύο σειρές του αρχείου KOR.TXT. Να συντάξετε πρόγραμμα σεFortran το οποίο να διαβάζει υψόμετρο H από το πληκτρολόγιο και αν είναι μεταξύ HA και HB ναυπολογίζει και να τυπώνει τις συντεταγμένες του σημείου με υψόμετρο H με γραμμική παρεμβολή.Αλλιώς να τυπώνει ότι το υψόμετρο H είναι εκτός.

module modgimplicit nonecontains

real function grampar(x1, y1, x2, y2, x) real, intent(in) :: x1, y1, x2, y2, x grampar = y1 + (y2-y1)/(x2-x1)*(x-x1)end function grampar

end module modg

program yps use modg implicit none real :: xa, ya, ha, xb, yb, hb, x, y, h open (11, file='kor.txt') read (11, *) xa, ya, ha read (11, *) xb, yb, hb read (*, *) h if (h>ha .and. h<hb .or. h<ha .and. h>hb) then x = grampar(ha, xa, hb, xb, h) y = grampar(ha, ya, hb, yb, h) write (*, *) x, y, h

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 115

Page 116: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

else write (*, *) 'Το ', h, ' είναι εκτός' end if close (11)end program yps open (11, file='kor.txt')

Εναλλακτικά η συνθήκη μπορεί να γραφεί: if ((h-ha)*(h-hb) < 0.0) then

Χρησιμοποιώντας μία συνάρτηση η οποία επιστρέφει .true. Αν ένας αριθμός x είναι μεταξύ a και bτο πρόγραμμα γίνεται πιο ευανάγνωστο:

module modgimplicit nonecontains

real function grampar(x1, y1, x2, y2, x) real, intent(in) :: x1, y1, x2, y2, x grampar = y1 + (y2-y1)/(x2-x1)*(x-x1)end function grampar

logical function inside(a, x, b) real, intent(in) :: a, x, b inside = .true. if (b > a) then inside = x>a .and. x<b else inside = x>b .and. x<a end ifend function inside

end module modg

program yps2 use modg implicit none real :: xa, ya, ha, xb, yb, hb, x, y, h open (11, file='kor.txt') read (11, *) xa, ya, ha read (11, *) xb, yb, hb read (*, *) h if (inside(ha, h, hb)) then x = grampar(ha, xa, hb, xb, h) y = grampar(ha, ya, hb, yb, h) write (*, *) x, y, h else write (*, *) 'Το ', h, ' είναι εκτός' end if close (11)

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 116

Page 117: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

end program yps2

Τέλος, χρησιμοποιώντας μητρώα για να αποθηκεύσουμε συντεταγμένες ενός σημείο, ωςσυνηθίζεται, το πρόγραμμα γίνεται:

module modgimplicit nonecontains

real function grampar(x1, y1, x2, y2, x) real, intent(in) :: x1, y1, x2, y2, x grampar = y1 + (y2-y1)/(x2-x1)*(x-x1)end function grampar

logical function inside(a, x, b) real, intent(in) :: a, x, b inside = .true. if (b > a) then inside = x>a .and. x<b else inside = x>b .and. x<a end ifend function inside

end module modg

program yps4 use modg implicit none real, dimension(3) :: ca, cb, c integer :: j open (11, file='kor.txt') read (11, *) (ca(j), j=1, 3) read (11, *) (cb(j), j=1, 3) read (*, *) c(3) if (inside(ca(3), c(3), cb(3))) then do j=1, 2 c(j) = grampar(ca(3), ca(j), cb(3), cb(j), c(3)) end do write (*, *) (c(j), j=1, 3) else write (*, *) 'Το ', c(3), ' είναι εκτός' end if close (11)end program yps4

ΆσκησηΝα συντάξετε πρόγραμμα το οποίο να βρίσκει πόσες ημέρες περνούν μεταξύ 2 ημερομηνιών. Προςδιευκόλυνση τα παρακάτω υποπρογράμματα:

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 117

Page 118: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

α) Υποπρόγραμμα που επιστρέφει αν ένα έτος είναι δίσεκτο. Ένα έτος είναι δίσεκτο αν διαιρείταιδια 4, εκτός αν διαιρείται δια 100 οπότε δεν είναι, εκτός αν διαιρείται δια 400 οπότε είναι.β) Υποπρόγραμμα που επιστρέφει το πλήθος ημερών ενός έτους.γ) Υποπρόγραμμα που επιστρέφει το πλήθος ημερών ενός μήνα συγκεκριμένου έτους.δ) Υποπρόγραμμα που ελέγχει αν μία ημερομηνία είναι σωστή και τυπώνει μήνυμα λάθους αν όχι.ε) Υποπρόγραμμα που επιστρέφει .true. Αν η πρώτη ημερομηνία είναι μεταγενέστερη της δεύτερηςημερομηνίας.στ) Υποπρόγραμμα που επιστρέφει το πλήθος ημερών που έχουν περάσει από την αρχή του έτουςενός έτους μέχρι μία ημερομηνία.

Θα συμβολίσουμε την ημερομηνία ως ένα ακέραιο μητρώο im με 3 στοιχεία που θα είναι η οαριθμός της ημέρα, ο αριθμός του μήνα και το έτος. Η συνάρτηση mod(i, j) επιστρέφει το υπόλοιποτης διαίρεσης i/j. Αν το i διαιρείται ακριβώς δια j επιστρέφει 0.

module moddaysimplicit nonecontains

logical function disekt(iet) !"Επιστρέφει .true. αν το έτος είναι δίσεκτο." integer, intent(in) :: iet disekt = mod(iet, 4) == 0 .and. (mod(iet, 100) /= 0 .or. mod(iet,400) == 0)end function disekt

integer function imerEt(iet)! "Επιστρέφει το πλήθος ημερών ενός έτους". integer, intent(in) :: iet imerEt = 365 if (disekt(iet)) imerEt = 366end function imerEt

integer function imerMhn(imhn, iet)! "Επιστρέφει το πλήθος ημερών ενός μήνα σε συγκεκριμένο έτος". integer, intent(in) :: imhn, iet if (imhn == 2 .and. disekt(iet)) then imerMhn = 29 else if (imhn == 2 .and. .not.disekt(iet)) then imerMhn = 28 else if (imhn < 8 .and. mod(imhn, 2) /= 0 .or. imhn >=8 .and.mod(imhn, 2) == 0) then imermhn = 31 else imermhn = 30 end ifend function imerMhn

subroutine test (ima)

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 118

Page 119: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

integer, dimension(3), intent(in) :: ima if (ima(3) <= 0) stop 'Πρέπει Ετος > 0' if (ima(2) < 1 .or. ima(2) > 12) stop 'Λάθος μήνας' if (ima(2) == 2 .and. ima(1) == 29 .and. .not.disekt(ima(3))) stop'Λάθος ημέρα' if (ima(1) < 1 .or. ima(1) > imerMhn(ima(2), ima(3))) stop 'Λάθοςημέρα'end subroutine test

logical function meg(ima, imb) !"Επιστρέφει .true. αν η ημερομηνία ima είναι μεταγενέστερη της imb." integer, dimension(3), intent(in) :: ima, imb integer :: i meg = .true. do i=3, 1, -1 if (ima(i) > imb(i)) return if (ima(i) < imb(i)) exit end do meg = .false.end function meg

integer function imer0(ima)! "Πλήθος ημερών από την αρχή του έτους, συμπεριλαμβάνοντας και τηνima." integer, dimension(3), intent(in) :: ima integer :: i imer0 = 0 do i=1, ima(2)-1 imer0 = imer0 + imerMhn(i, ima(3)) end do imer0 = imer0 + ima(1)end function imer0

end module moddays

program days use moddays implicit none integer, dimension(3) :: ima, imb integer :: i, k, n read (*, *) (ima(i), i=1, 3) !Ημέρα, μήνας, έτος call test (ima) read (*, *) (imb(i), i=1, 3) !Ημέρα, μήνας, έτος call test (imb) if (meg(ima, imb)) then do i=1, 3 k = ima(i) ima(i) = imb(i) imb(i) = k end do

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 119

Page 120: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

end if n = imer0(imb) do i=imb(3)-1, ima(3), -1 n = n + imerEt(i) end do n = n - imer0(ima) write (*, *) nend program days

Χειρισμός μητρώωνΕπειδή τα μητρώα χρησιμοποιούνται από τους μηχανικούς πάρα πολύ συχνά, η Fortran δίνει πολύμεγάλες δυνατότητες στο χειρισμό τους. Καταρχήν υπάρχει δυνατότητα να κάνουμε πράξεις σε όλοτο μητρώο. Οι συνάρτηση SUM(A) δίνει το άθροισμα όλων των στοιχείων ενός μητρώου:

program x implicit none INTEGER, DIMENSION(3) :: K integer :: j K(1) = 1 K(2) = 3 K(3) = 5 J = SUM(K) !Λαμβάνει την τιμή 9 write (*, *) jend program x

Επίσης μπορούμε να δώσουμε τιμές σε όλα τα στοιχεία του μητρώου σε μία εντολή:

program x implicit none INTEGER, DIMENSION(3) :: K integer :: j K = (/1, 3, 5/) J = SUM(K) !Λαμβάνει την τιμή 9 write (*, *) jend program x

Αν θέλουμε μόνο να υπολογίσουμε το άθροισμα των τριών αριθμών μπορούμε να παραλείψουμε τοK:

program x implicit none integer :: j J = SUM((/1, 3, 5/)) !Λαμβάνει την τιμή 9 write (*, *) jend program x

Μπορούμε να δώσουμε τιμές σε ένα μητρώο με έμμεσο βρόχο:program x

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 120

Page 121: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

implicit none INTEGER, DIMENSION(6) :: K integer :: j K = (/(J, J=1, 11, 2)/) !Λαμβάνει τα στοιχεία: 1, 3, 5, 7, 9, 11 J = SUM(K) !Λαμβάνει την τιμή 9 write (*, *) jend program x

Μπορούμε να τυπώσουμε ένα ολόκληρο μητρώο:

program x implicit none INTEGER, DIMENSION(6) :: K integer :: j K = (/(J, J=1, 11, 2)/) !Λαμβάνει τα στοιχεία: 1, 3, 5, 7, 9, 11 write (*, *) K !Τυπώνει 1, 3, 5, 7, 9, 11end program x

Επίσης μπορούμε να διαβάσουμε ένα ολόκληρο μητρώο:

program x implicit none REAL, DIMENSION(6) :: F integer :: j read (*, *) F !Διαβάζει 6 αντοχές δοκιμίων από 1 σειρά write (*, *) SUM(f)/SIZE(F) !Τυπώνει το μέσο όρο των αντοχώνend program x

Μπορούμε να κάνουμε πράξεις με μόνο ένα τμήμα του μητρώου (υπομητρώο). Ένα τμήμα τουμητρώου δηλώνουμε να άνω και κάτω τελεία:

K(I1:I2)

Το τμήμα αυτό έχει τα στοιχεία I1, I1+1, I1+2, ..., I2 του μητρώου K. Αν παραληφθεί το I1θεωρείται ως 1 (ή όπως θα δούμε αργότερα, όποιος είναι ο δείκτης του πρώτου στοιχείου τουμητρώου). Αν παραληφθεί το I2 θεωρείται ως ο δείκτης του τελευταίου στοιχείου του μητρώου. Ανπαραληφθούν και τα 2, είναι το ίδιο με το μητρώο K:

program x implicit none INTEGER, DIMENSION(6) :: K integer :: j K = (/(J, J=1, 11, 2)/) !Λαμβάνει τα στοιχεία: 1, 3, 5, 7, 9, 11 write (*, *) K(2:4) !Τυπώνει 3, 5, 7 write (*, *) K(:2) !Τυπώνει 1, 3 write (*, *) K(4:) !Τυπώνει 7, 9, 11 write (*, *) K(:) !Τυπώνει 1, 3, 5, 7, 9, 11end program x

Εκτός από αρχικό και τελικό στοιχείο μπορούμε να θέσουμε και ένα βήμα:

K(I1:I2:I3)

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 121

Page 122: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Το τμήμα αυτό έχει τα στοιχεία I1, I1+I3, I1+2*I3, ..., I2 (το στοιχείο I2 δεν θα περιλαμβάνεται ανI2-I1 δεν διαιρείται δια I3). Αν παραληφθεί το I3 θεωρείται ως 1:

program x implicit none INTEGER, DIMENSION(6) :: K integer :: j K = (/(J, J=1, 11, 2)/) !Λαμβάνει τα στοιχεία: 1, 3, 5, 7, 9, 11 write (*, *) K(2:6:2) !Τυπώνει 3, 7, 11 write (*, *) K(:2:3) !Τυπώνει 1 write (*, *) K(4::2) !Τυπώνει 7, 11 write (*, *) K(::3) !Τυπώνει 1, 7 !write (*, *) K(2:4:) !Λάθος: Αν δεν μπει το βήμα, δεν πρέπει ναμπει ούτε η άνω και κάτω τελείαend program x

Πράξεις μητρώωνΜπορούμε να προσθέσουμε μαζικά ένα αριθμό σε όλα τα στοιχεία ενός μητρώου:

program x implicit none INTEGER, DIMENSION(6) :: K integer :: j K = (/(J, J=1, 11, 2)/) !Λαμβάνει τα στοιχεία: 1, 3, 5, 7, 9, 11 write (*, *) K !Τυπώνει 1, 3, 5, 7, 9, 11 K = K + 10 write (*, *) K !Τυπώνει 11, 13, 15, 17, 19, 21 K(1:3) = K(1:3) + 100 write (*, *) K !Τυπώνει 111, 113, 115, 17, 19, 21end program x

Μπορούμε να θέσουμε τα αποτελέσματα πράξεων σε άλλο μητρώο αρκεί να έχει τον ίδιο αριθμόδιαστάσεων και τον ίδιο αριθμό στοιχείων:

program x implicit none INTEGER, DIMENSION(6) :: K, L INTEGER, DIMENSION(3) :: KA integer :: j K = (/(J, J=1, 11, 2)/) !Λαμβάνει τα στοιχεία: 1, 3, 5, 7, 9, 11 write (*, *) K !Τυπώνει 1, 3, 5, 7, 9, 11 L = K + 10 write (*, *) L !Τυπώνει 11, 13, 15, 17, 19, 21 KA = K(1:3) + 100 write (*, *) KA !Τυπώνει 101, 103, 105end program x

Εκτός από πρόσθεση, μπορούμε να κάνουμε όλες τις πράξεις με μητρώα (αφαίρεση,πολλαπλασιασμός, διαίρεση, ύψωση σε δύναμη):

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 122

Page 123: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

program x implicit none INTEGER, DIMENSION(6) :: K, L INTEGER, DIMENSION(3) :: KA integer :: j K = (/(J, J=1, 11, 2)/) !Λαμβάνει τα στοιχεία: 1, 3, 5, 7, 9, 11 write (*, *) K !Τυπώνει 1, 3, 5, 7, 9, 11 L = K*2 + 10 write (*, *) L !Τυπώνει 12, 16, 20, 24, 28, 32 KA = K(1:3) ** 3 write (*, *) KA !Τυπώνει 1, 27, 125end program x

Μπορούμε ακόμα να εφαρμόσουμε κάποιες ειδικές συναρτήσεις (elemental - στοιχειακές) σε όλατα στοιχεία ενός μητρώου. Στοιχειακές είναι γενικά οι μαθηματικές συναρτήσεις (sin(x), sqrt(x)κλπ). Πιο συγκεκριμένα οι στοιχειακές (ELEMENTAL) συναρτήσεις πρέπει να επιστρέφουν μίαβαθμωτή τιμή, να έχουν παραμέτρους που είναι βαθμωτές και INTENT(IN), και να μην έχουνπαρενέργειες (όπως να αλλάζουν τιμές στις παραμέτρους, σε κοινές μεταβλητές, ναγράφουν/διαβάζουν αρχεία ή την οθόνη ή το πληκτρολόγιο, ή να έχουν STOP).

program x implicit none REAL, DIMENSION(6) :: B, C integer :: j B = (/4.0, 9.0, 16.0, 25.0, 100.0, 625.0/) C = SQRT(B) WRITE (*, *) C !Τυπώνει 2.0, 3.0, 4.0, 5.0, 10.0, 25.0end program x

Μπορούμε να κάνουμε πράξεις μεταξύ μητρώων αρκεί να έχουν τον ίδιο αριθμό διαστάσεων καιτον ίδιο αριθμό στοιχείων:

program x implicit none INTEGER, DIMENSION(6) :: K, L INTEGER, DIMENSION(3) :: KA integer :: j K = (/(J, J=1, 11, 2)/) !Λαμβάνει τα στοιχεία: 1, 3, 5, 7, 9, 11 L = (/-1, 1, 10, 20, 30, 100/) write (*, *) K+L !Τυπώνει 0, 4, 15, 27, 39, 111 L = K**2 + L**2 write (*, *) L !Τυπώνει 2, 10, 125, 449, 981, 10121 KA = K(1:3) * (/10, 100, 1000/) write (*, *) KA !Τυπώνει 10, 300, 5000end program x

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

program x implicit none

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 123

Page 124: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

INTEGER, DIMENSION(6) :: K, L, M integer :: j K = (/(J, J=1, 11, 2)/) !Λαμβάνει τα στοιχεία: 1, 3, 5, 7, 9, 11 L = (/-1, 1, 10, 20, 30, 100/) M = K + L + 10 write (*, *) M !Τυπώνει 10, 14, 25, 37, 49, 121 M(1:5) = K(2:6) - K(1:5) write (*, *) M(1:5) !Τυπώνει 2, 2, 2, 2, 2 write (*, *) M !Τυπώνει 2, 2, 2, 2, 2, 121end program x

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 124

Page 125: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Δευτέρα 21/7/2014 10:45-14:30, B' πολ. Μηχανικών, Προγραμματισμός Η/Υ, θεωρία, Α Τμήμα (01AB)

Παλιό θέμαΣτο αρχείο OIKOP.TXT έχουν γραφεί οι συντεταγμένες των κορυφών ενός οικοπέδου. Στην πρώτησειρά έχει γραφεί το πλήθος N των κορυφών και σε κάθε μία από τις επόμενες σειρές οισυντεταγμένες X και Y της κάθε κορυφής. Σε κάθε σειρά η συντεταγμένη X καταλαμβάνει 15θέσεις και έχει 3 δεκαδικά ψηφία. Παρομοίως και η Y.Το εμβαδό E και η περίμετρος P του οικοπέδου δίνονται από:

E=12∣∑

i=1

N

( X i+1−X i )(Y i+1+Y i )∣ P=∑i=1

N

√( X i+1−X i )2+(Y i+1−Y i )

2

με τη σύμβαση ότι XN+1=X1, YN+1=Y1

Να συντάξετε πρόγραμμα σε Fortran και το αντίστοιχο διάγραμμα ροής, το οποίο να διαβάζει τιςσυντεταγμένες με FORMAT και να υπολογίζει και να τυπώνει το εμβαδόν και την περίμετρο τουοικοπέδου με παρόμοιο FORMAT.

(3.5 μονάδες)

program oik implicit none real, dimension(:), allocatable :: x, y integer :: i, n real :: e, p open (11, file='oikop.txt', status='old') read (11, *) n allocate (x(n+1), y(n+1)) do i=1, n read (11, '(f15.0, f15.0)') x(i), y(i) end do x(n+1) = x(1) y(n+1) = y(1) e = 0.0 p = 0.0 do i=1, n e = e + (x(i+1) - x(i)) * (y(i+1) + y(i)) p = p + sqrt((x(i+1) - x(i))**2 + (y(i+1) - y(i))**2) end do e = abs(e)*0.5 write (*, '(a, f15.3, a, f15.3)') 'εμβαδό', e, ' περίμετρος', p close (11)end program oik

Χρησιμοποιώντας πράξεις μητρώων το πρόγραμμα γίνεται μικρότερο (και πιθανότατα πιογρήγορο) , αλλά όχι απαραίτητα πιο κατανοητό:

program oik2 implicit none real, dimension(:), allocatable :: x, y integer :: i, n real :: e, p open (11, file='oikop.txt', status='old') read (11, *) n

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 125

Page 126: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

allocate (x(n+1), y(n+1)) do i=1, n read (11, '(f15.0, f15.0)') x(i), y(i) end do x(n+1) = x(1) y(n+1) = y(1) e = 0.0 p = 0.0 e = sum( (x(2:n+1) - x(1:n)) * (y(2:n+1) + y(1:n)) ) e = abs(e)*0.5 p = sum( sqrt((x(2:n+1) - x(1:n))**2 + (y(2:n+1) - y(1:n))**2) ) write (*, '(a, f15.3, a, f15.3)') 'εμβαδό', e, ' περίμετρος', p close (11)end program oik2

ΠαράδειγμαΝα συντάξετε πρόγραμμα που να διαβάζει δορυφορική φωτογραφία (αποχρώσεις του γκρι) απόαρχείο με κατάληξη .RAW, να την κάνει 10% πιο φωτεινή και να τη γράφει σε αρχείο με το ίδιοπρόθεμα και κατάληξη 1.RAW. Στην πρώτη γραμμή του αρχείου .RAW γράφονται οι διαστάσεις τιςφωτογραφίας πλάτος NB x ύψος NH σε pixels. Σε κάθε μία από τις επόμενες σειρές γράφονται οιαποχρώσεις του γκρι κάθε pixels μίας γραμμής της φωτογραφίας ως ακέραιοι από 0 έως 255. Σεκάθε απόχρωση πρέπει να προστεθεί το νούμερο 10% * 256, αλλά αν το άθροισμα είναιμεγαλύτεροι από 255, πρέπει να γίνει 255. Το πρόθεμα των αρχείων διαβάζεται από τοπληκτρολόγιο.

program doryf1 implicit none character(len=80) pro integer, dimension(:), allocatable :: igray integer :: nb, nh, i, j, kfot write (*, *) 'Δώστε όνομα αρχείων χωρίς την κατάληξη .raw' read (*, '(a)') pro open (11, file=trim(pro)//'.raw', status='old') open (12, file=trim(pro)//'1.raw') read (11, *) nb, nh write (12, *) nb, nh allocate (igray(nb)) kfot = int(256.0*0.10) do i=1, nh read (11, *) (igray(j), j=1, nb) do j=1, nb igray(j) = igray(j)+kfot if (igray(j) > 255) igray(j) = 255 end do write (12, *) (igray(j), j=1, nb) end do close (11) close (12)end program doryf1

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 126

Page 127: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

Προκειμένου να χρησιμοποιήσουμε πράξεις μητρών αντικαθιστούμε το IF με κλήση τηςσυνάρτησης min (που είναι στοιχειακή) και κάνeι το ίδιο:

program doryf2 implicit none character(len=80) pro integer, dimension(:), allocatable :: igray integer :: nb, nh, i, j, kfot write (*, *) 'Δώστε όνομα αρχείων χωρίς την κατάληξη .raw' read (*, '(a)') pro open (11, file=trim(pro)//'.raw', status='old') open (12, file=trim(pro)//'1.raw') read (11, *) nb, nh write (12, *) nb, nh allocate (igray(nb)) kfot = int(256.0*0.10) do i=1, nh read (11, *) (igray(j), j=1, nb) do j=1, nb igray(j) = min(igray(j)+kfot, 255) end do write (12, *) (igray(j), j=1, nb) end do close (11) close (12)end program doryf2

Στη συνέχεια αντικαθιστούμε τους εσωτερικούς βρόχους (άμεσους και έμμεσους) με πράξειςμητρώων:

program doryf3 implicit none character(len=80) pro integer, dimension(:), allocatable :: igray integer :: nb, nh, i, kfot write (*, *) 'Δώστε όνομα αρχείων χωρίς την κατάληξη .raw' read (*, '(a)') pro open (11, file=trim(pro)//'.raw', status='old') open (12, file=trim(pro)//'1.raw') read (11, *) nb, nh write (12, *) nb, nh allocate (igray(nb)) kfot = int(256.0*0.10) do i=1, nh read (11, *) igray igray = min(igray+kfot, 255) write (12, *) igray end do close (11) close (12)end program doryf3

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 127

Page 128: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

ΆσκησηΓια το προσδιορισμό του ολικού πληθυσμού από το πλήθος των εργαζομένων, έγιναν οι εξήςμετρήσεις σε n=5 νοικοκυριά μίας πόλης:

Νοικοκυριό1 1 12 5 33 3 24 9 55 7 4

ΠλήθοςΜελώνYi

ΠλήθοςΕργαζομ.

Xi

Υποθέτοντας γραμμική σχέση y=Ax+B, οι συντελεστές A, B υπολογίζονται:

A=n∑ x i y i−(∑ x i)(∑ y i)

n∑ x i2−(∑ x i )

2 , B=∑ y i−A∑ xi

n , i=1,2,...,n

Το μέσο τετραγωνικό σφάλμα RMSE υπολογίζεται ως:

RMSE=√∑ [ y i−(Axi+B)]2

n , i=1,2,...,n

Να συντάξετε πρόγραμμα σε Fortran το οποίο να υπολογίζει και να τυπώνει στην οθόνη τουςσυντελεστές Α, Β και το μέσο τετραγωνικό σφάλμα για τις συγκεκριμένες μετρήσεις. Επίσης νατυπώνει το ολικό πληθυσμό (y) για 5 συνοικίες με πλήθος εργαζομένων (x) 1500, 1990, 2345, 325και 589 αντίστοιχα.

program pol1 implicit none real, dimension(5) :: x, y real :: an, sx, sy, sxy, sx2, a, b, rmse integer :: i y(1) = 1.0 y(2) = 5.0 y(3) = 3.0 y(4) = 9.0 y(5) = 7.0 x(1) = 1.0 x(2) = 3.0 x(3) = 2.0 x(4) = 5.0 x(5) = 4.0 sx = 0.0 sy = 0.0 sxy = 0.0 sx2 = 0.0 do i=1, size(x) sx = sx + x(i) sy = sy + y(i) sxy = sxy + x(i) * y(i) sx2 = sx2 + x(i)**2 end do an = real(size(x)) a = (an*sxy - sx*sy) / (an*sx2 - sx**2) b = (sy - a*sx) / an rmse = 0.0

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 128

Page 129: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

do i=1, size(x) rmse = rmse + (y(i) - (a*x(i)+b))**2 end do rmse = sqrt(rmse / an) write (*, *) a, b, rmse write (*, *) a*1500.0+b write (*, *) a*1900.0+b write (*, *) a*2345.0+b write (*, *) a*325.0+b write (*, *) a*589.0+bend program pol1

Χρησιμοποιώντας πράξεις μητρώων το πρόγραμμα γίνεται πιο κομψό:

program po2 implicit none real, dimension(5) :: x, y real :: an, sx, sy, a, b, rmse y = (/1.0, 5.0, 3.0, 9.0, 7.0/) x = (/1.0, 3.0, 2.0, 5.0, 4.0/) sx = sum(x) sy = sum(y) an = real(size(x)) a = (an*sum(x*y) - sx*sy) / (an*sum(x**2) - sx**2) b = (sy - a*sx) / an rmse = sqrt(sum((y - (a*x+b))**2) / an) write (*, *) a, b, rmse x = (/1500.0, 1900.0, 2345.0, 325.0, 589.0/) write (*, *) a*x+bend program po2

Παλιό θέμαΝα συντάξετε πρόγραμμα σε Fortran και το αντίστοιχο διάγραμμα ροής, το οποίο να υπολογίζεικαι να τυπώνει το όριο των παρακάτω ακολουθιών αν συγκλίνουν, αλλιώς να τυπώνει ότι δενσυγκλίνουν:

s(n) = 1+1/2+1/3+1/4+1/5 + ...+ 1/nt(n) = -log(n)+1+1/2+1/3+1/4+1/5 + ...+ 1/nu(n) = 1-1/2+1/3-1/4+1/5 - ... ± 1/n

Να θεωρήσετε ότι μία ακολουθία πρακτικά δεν συγκλίνει όταν μετά από 1000 όρους δεν έχειεπιτευχθεί ακρίβεια 4 δεκαδικών ψηφίων. Ο λογάριθμος μπορεί να υπολογιστεί με τη συνάρτησηALOG(X), για παράδειγμα ο λογάριθμος του 15 υπολογίζεται ως: C = ALOG(15.0)

(4 μονάδες)

program syg1 implicit none real :: s, sp, t, tp, an, u, up, pr integer :: n logical :: sygklish sp = 1.0 sygklish = .false. do n=2, 1000

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 129

Page 130: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

s = sp + 1.0/float(n) if (abs(s-sp) < 1.0e-4) then sygklish = .true. exit end if sp = s end do if (sygklish) then write(*, *) 'Η ακολουθία s(n) συγκλίνει: ', s else write (*, *) 'Η ακολουθία s(n) δεν συγκλίνει' end if

tp = -alog(1.0) + 1.0 sygklish = .false. do n=2, 1000 an = n t = tp + alog(float(n-1)) - alog(an) + 1.0/an if (abs(t-tp) < 1.0e-4) then sygklish = .true. exit end if tp = t end do if (sygklish) then write(*, *) 'Η ακολουθία t(n) συγκλίνει: ', t else write (*, *) 'Η ακολουθία t(n) δεν συγκλίνει' end if

up = 1.0 pr = -1.0 sygklish = .false. do n=2, 1000 an = n u = up + pr/an if (abs(u-up) < 1.0e-4) then sygklish = .true. exit end if up = u pr = -pr end do if (sygklish) then write(*, *) 'Η ακολουθία u(n) συγκλίνει: ', u else write (*, *) 'Η ακολουθία u(n) δεν συγκλίνει' end ifend program syg1

Χρήση υποπρογραμμάτων και ονοματισμός σταθερών απλουστεύει το πρόγραμμα σημαντικά:

module modsynart

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 130

Page 131: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

implicit noneinteger, parameter :: MITER=1000real, parameter :: EPS=1.0e-4contains

subroutine sygs() integer :: n real :: s, sp sp = 1.0 do n=2, MITER s = sp + 1.0/real(n) if (abs(s-sp) < EPS) then write (*, *) 'Η ακολουθία s(n) συγκλίνει: ', s return end if sp = s end do write (*, *) 'Η ακολουθία s(n) δεν συγκλίνει'end subroutine sygs

subroutine sygt() real :: t, tp integer :: n tp = -alog(1.0) + 1.0 do n=2, MITER t = tp + alog(real(n-1)) - alog(real(n)) + 1.0/real(n) if (abs(t-tp) < EPS) then write (*, *) 'Η ακολουθία t(n) συγκλίνει: ', t return end if tp = t end do write (*, *) 'Η ακολουθία t(n) δεν συγκλίνει'end subroutine sygt

subroutine sygu() real :: u, up, pr integer :: n up = 1.0 pr = -1.0 do n=2, MITER u = up + pr/real(n) if (abs(u-up) < EPS) then write (*, *) 'Η ακολουθία u(n) συγκλίνει: ', u return end if up = u pr = -pr end do write (*, *) 'Η ακολουθία u(n) δεν συγκλίνει'end subroutine sygu

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 131

Page 132: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

end module modsynart

program syg2 use modsynart implicit none call sygs() call sygt() call sygu()end program syg2

Παλιό θέμαΝα συντάξετε πρόγραμμα σε Fortran το οποίο να διαβάζει ένα θετικό ακέραιο αριθμό από τοπληκτρολόγιο, ο οποίος έχει 5 ή λιγότερα ψηφία, και να υπολογίζει το άθροισμα K των ψηφίωντου. Αν το άθροισμα K είναι διψήφιος αριθμός, να αντικαθιστά το K με το άθροισμα των δύοψηφίων του. Στη συνέχεια να ελέγχει αν το K διαιρείται δια 3 και να τυπώνει στην οθόνη“ΔΙΑΙΡΕΙΤΑΙ” ή “ΔΕΝ ΔΙΑΙΡΕΙΤΑΙ” αναλόγως.

(2.5 μονάδες)

program math1 implicit none integer :: n, m, idx, ix, ie, id, im, k, k1 read (*, *) n m = n idx = m / 10000 m = m - idx*10000 ix = m / 1000 m = m - ix*1000 ie = m / 100 m = m - ie*100 id = m / 10 m = m - id*10 im = m / 1 !write (*, *) idx, ix, ie, id, im k = idx + ix + ie + id + im !write (*, *) 'k=', k if (k > 9) then m = k id = k / 10 m = m - id*10 im = m / 1 !write (*, *) id, im k = id + im !write (*, *) 'k=', k end if k1 = k/3 if (k1*3 == k) then write (*, *) 'Διαιρείται δια 3' else write (*, *) 'Δεν Διαιρείται δια 3' end if

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 132

Page 133: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

end program math1

Χρησιμοποιώντας βρόχους, μητρώα και τη συνάρτηση mod() το πρόγραμμα γίνεται:

program math2 implicit none integer :: n, i integer, dimension(5) :: k character(len=5) :: a read (*, *) n do i=1, 5 k(i) = n/10**(i-1) n = n - k(i) * 10**(i-1) end do n = sum(k) do i=1, 2 k(i) = n/10**(i-1) n = n - k(i) * 10**(i-1) end do n = sum(k(1:2)) if (mod(n, 3) == 0) then write (*, *) 'Διαιρείται δια 3' else write (*, *) 'Δεν διαιρείται δια 3' end ifend program math2

Τέλος με διαφορετικό τρόπο, χρησιμοποιώντας read/write σε μεταβλητή χαρακτήρων) τοπρόγραμμα γίνεται:

program math3 implicit none integer :: n integer, dimension(5) :: k character(len=5) :: a read (*, *) n write (a, '(i5)') n read (a, '(5i1)') k n = sum(k) write (a, '(i2)') n read (a, '(2i1)') k(1:2) n = sum(k(1:2)) if (mod(n, 3) == 0) then write (*, *) 'Διαιρείται δια 3' else write (*, *) 'Δεν διαιρείται δια 3' end ifend program math3

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 133

Page 134: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

ΠαράδειγμαΠόλεις θα συνδεθούν με σιδηροδρομική γραμμή σε μορφή κλειστού βρόχου. Υποθέτοντας ότι ηχάραξη της σιδ. γραμμής θα είναι ευθύγραμμη, να υπολογιστεί η σειρά με την οποία πρέπει νασυνδεθούν οι πόλεις έτσι ώστε να έχουμε τις λιγότερες επιπτώσεις στο περιβάλλον (δηλαδή τοελάχιστο μήκος σιδ. Γραμμής). Οι συντεταγμένες των πόλεων (που θεωρούνται σημεία) δίνονταιστο αρχείο cities.txt. Στην πρώτη σειρά του αρχελιου ελίναι γραμμένο το πλήθος των πόλεων.

Συνδυασμοί: N! (για N=20 N! = 1018)

module modcitimplicit nonereal, dimension(:), allocatable :: x, yinteger :: ncitcontains

subroutine synd(isynd) integer, dimension(:), intent(out) :: isynd integer :: i, j1, j2, is1 real :: x isynd = (/(i, i=1, ncit)/) call srand(time()) do i=1, ncit x = rand(0) j1 = x*real(ncit) + 1 x = rand(0) j2 = x*real(ncit) + 1 if (j1 == j2) cycle is1 = isynd(j1) isynd(j1) = isynd(j2) isynd(j2) = is1 end doend subroutine synd

real function dis(isynd) integer, dimension(:), intent(in) :: isynd integer :: i, j, jp dis = 0.0 jp = ncit do i=1, ncit j = isynd(i) dis = dis + sqrt((x(jp)-x(j))**2 + (y(jp)-y(j))**2) jp = j end doend function dis

subroutine beltist(dmin, isyndmin) integer, dimension(:), intent(out) :: isyndmin real, intent(out) :: dmin integer, dimension(:), allocatable :: isynd integer :: i

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 134

Page 135: Δευτέρα 7/4/2014 10:45-14:30, B' πολ. Μηχανικών ...mycourses.ntua.gr/courses/CIVIL1058/document/simeioseis_fortran… · Δευτέρα 7/4/2014 10:45-14:30, b'

real :: d dmin = 1.0e30 allocate (isynd(ncit)) do i=1, ncit*5000 call synd(isynd) d = dis(isynd) if (d < dmin) then dmin = d isyndmin = isynd end if end doend subroutine beltist

subroutine readc integer :: i open (11, file='cities.txt') read (11, *) ncit allocate (x(ncit), y(ncit)) do i=1, ncit read(11, *) x(i), y(i) end do close (11)end subroutine readc

end module modcit

program cit use modcit implicit none integer, dimension(:), allocatable :: isyndmin real :: dmin integer :: i, j call readc() allocate(isyndmin(ncit)) call beltist(dmin, isyndmin) write (*, *) isyndmin write (*, *) dmin do i=1, ncit j = isyndmin(i) write (*, '(2f15.3)') x(j), y(j) end doend program cit

Σημειώσεις Fortran95 2013-2014a – Α. Στάμος 135