THMMY.gr

Μαθήματα Βασικού Κύκλου => Δομημένος Προγραμματισμός => Topic started by: Apostolof on March 29, 2016, 20:57:50 pm



Title: [Δομημένος Προγραμματισμός] Άσκηση 5 (Hμ/νία λήξης: 10/4/2016)
Post by: Apostolof on March 29, 2016, 20:57:50 pm
Άσκηση 5


Σημείωση για την παράδοση
Στο elearning θα ανεβάσετε σε ένα αρχείο τις απαντήσεις σας
Η ονομασία του αρχείου θα έχει ως εξής:
Α5-Αριθμος Μητρώου π.χ Α5-9000


Να φτιάξετε ένα πρόγραμμα το οποίο να υπολογίζει τον ακόλουθο τύπο: f(x)=(x^3)+(x*y*z) Οι πράξεις που βρίσκονται μέσα στις παρενθέσεις θα πρέπει να υπολογίζονται από διαφορετικές συναρτήσεις. Ο χρήστης θα πρέπει να δίνει το x,y,z και στο τέλος να τυπώνεται το αποτέλεσμα της συνάρτησης. Οι συναρτήσεις που θα δημιουργήσετε θα πρέπει να έχουν τις αντίστοιχες παραμέτρους και να επιστρέφουν τους κατάλληλους τύπους δεδομένων.


Λήξη υποβολής εμπρόθεσμων εργασιών: Κυριακή, 10 Απρίλιος 2016, 12:00 πμ



Title: Re: [Δομημένος Προγραμματισμός] Άσκηση 5 (Hμ/νία λήξης: 10/4/2016)
Post by: potirikolonato on March 31, 2016, 16:09:24 pm
Σημειώνω ότι ο Γενειατάκης είπε να δώσουμε μια γενικότερη προσέγγιση για την επίλυση της Άσκησης.
Υπέθεσα ότι εννοεί να δώσουμε μεγαλύτερο εύρος τιμών για τα x,y,z. H λύση που έδωσα είναι εξής:
Code:
#include <stdio.h>

double kybos(float);
double ginomeno(float,float,float);

int
main() {
float x,y,z;
double fu;

printf("Δώσε το x το y το z\n");
scanf("%f%f%f",&x,&y,&z);
fu=kybos(x)+ginomeno(x,y,z);
printf("To αποτελεσμα της f(x) είναι : %f\n",fu );

return 0;
}

double kybos(float x){
double t;
t=x*x*x;
return t;
}

double ginomeno(float x, float y, float z){
double t;
t=x*y*z;
return t;
}
Προγραμματιστικές συμβουλές, βελτιώσεις ή ακόμα και διόρθωσεις είναι ευπρόσδεκτες.
Τρέχει κανονικά το πρόγραμμα πάντως.  :) :)

edit:Μια μικρή διόρθωση στον κώδικα



Title: Re: [Δομημένος Προγραμματισμός] Άσκηση 5 (Hμ/νία λήξης: 10/4/2016)
Post by: Egkelados on March 31, 2016, 17:04:21 pm
Αν στις συναρτήσεις γράφαμε αντί για το 
Code:
double kybos(float x){
   double t;
   t=x*x*x;
   return t;
}

ένα πιο απλό
Code:
double kybos(float x){
  return x*x*x;
}

θα υπήρχε κάποια βελτίωση όσον αφορά την ταχύτητα εκτέλεσης του προγράμματος; Και αν σε αυτό τον κώδικα επειή είναι μικρός είναι απειροελάχιστη σε κώδικες πολλών σειρών παίζει ρόλο αυτό;;;


Title: Re: [Δομημένος Προγραμματισμός] Άσκηση 5 (Hμ/νία λήξης: 10/4/2016)
Post by: potirikolonato on March 31, 2016, 17:09:17 pm
Επίσης, τι απ'τα δύο θεωρείται ως πιο ευανάγνωστο;;


Title: Re: [Δομημένος Προγραμματισμός] Άσκηση 5 (Hμ/νία λήξης: 10/4/2016)
Post by: Apostolof on March 31, 2016, 18:22:31 pm
Πολύ καλός Assassin. Σωστότατος και open source :)
Βέβαια καλό θα είναι αν έχεις έτοιμο πρόγραμμα που λειτουργεί και όχι απορίες να το ποστάρεις μετά τη λήξη της διορίας.

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

Σχετικά με το χρόνο εκτέλεσης μπορούμε να δούμε τα αποτελέσματα αυτού:
Code:
#include <stdio.h>
#include <time.h>
#define REP 1000000

double kybos1(float);
double ginomeno1(float,float,float);
double kybos2(float);
double ginomeno2(float,float,float);

int main() {
clock_t begin1, end1,begin2, end2;
double time_spent1,time_spent2;
float x,y,z;
double fu;
int i;
begin1 = clock();
for(i=0;i<REP;i++){
    x=y=z=i;
    printf("To αποτελεσμα της f(x) είναι : %f\n",kybos1(x)+ginomeno1(x,y,z) );
}
end1 = clock();
time_spent1 = (double)(end1 - begin1) / CLOCKS_PER_SEC;
begin2 = clock();
for(i=0;i<REP;i++){
    x=y=z=i;
    fu=kybos2(x)+ginomeno2(x,y,z);
    printf("To αποτελεσμα της f(x) είναι : %f\n",fu );
}
end2 = clock();
time_spent2 = (double)(end2 - begin2) / CLOCKS_PER_SEC;
printf("Time 1 = %lf\nTime 2 = %lf",time_spent1,time_spent2);
return 0;
}
double kybos1(float x){
return x*x*x;
}
double ginomeno1(float x, float y, float z){
return x*y*z;
}
double kybos2(float x){
double t;
t=x*x*x;
return t;
}
double ginomeno2(float x, float y, float z){
double t;
t=x*y*z;
return t;
}

Εγώ το έτρεξα μέχρι τις 1000000 επαναλήψεις και έβγαλε:
Code:
Time 1 = 165.24
Time 2 = 164.69

Δηλαδή η γραφή του Assassin είναι γρηγορότερη! Αυτό υποθέτω ότι συμβαίνει γιατί ο compiler που χρησιμοποίησα (mingw) κάνει καλύτερο optimization στη μορφή που το έχει γράψει ο Assassin από ότι στην άλλη. Ο ίδιος κώδικας όταν χρησιμοποίησα gnu gcc έδωσε:
Code:
Time 1 = 160.23
Time 2 = 160.26
Αν κάποιος ξέρει περισσότερα ας συμπληρώσει.


Title: Re: [Δομημένος Προγραμματισμός] Άσκηση 5 (Hμ/νία λήξης: 10/4/2016)
Post by: potirikolonato on March 31, 2016, 19:22:22 pm
Πολύ καλός Assassin. Σωστότατος και open source :)
Βέβαια καλό θα είναι αν έχεις έτοιμο πρόγραμμα που λειτουργεί και όχι απορίες να το ποστάρεις μετά τη λήξη της διορίας.
Ουπς, έχεις δίκιο.
Κατα τ'άλλα ευχαριστώ!!


Title: Re: [Δομημένος Προγραμματισμός] Άσκηση 5 (Hμ/νία λήξης: 10/4/2016)
Post by: Egkelados on March 31, 2016, 20:42:50 pm
αυτές οι διαφορές στο χρόνο τι αντιπροσωπεύουν ακριβώς ? ( εννοώ ms , μs κλπ ) και επίσης είναι τόσο "σημαντικές" ?


Title: Re: [Δομημένος Προγραμματισμός] Άσκηση 5 (Hμ/νία λήξης: 10/4/2016)
Post by: Apostolof on March 31, 2016, 21:51:32 pm
Οι χρόνοι είναι σε seconds. Δηλαδή οι διαφορές είναι 0,55s και 0,03s αντίστοιχα. Το πόσο σημαντικές είναι εξαρτάται από το τι κάνεις. Όσο μεγαλύτερη η εφαρμογή τόσο μεγαλύτερη θα είναι η συνολική διαφορά στο χρόνο εκτέλεσης. Επίσης εξαρτάται από αν επιδιώκεις βελτιστοποίηση και αποτελεσματικότητα στο χρόνο ή στο χώρο (ή και στα δύο).


Title: Re: [Δομημένος Προγραμματισμός] Άσκηση 5 (Hμ/νία λήξης: 10/4/2016)
Post by: leukosaraphs! on March 31, 2016, 22:01:48 pm
Παιδες , εγω εχω αλλο προβλημα
Ενω παταω compile, και μου βγαζει αυτο το κοκκινο τετραγωνακι οτι υπαρχει λαθος ..δν μου βγαζει κατω απο τον κωδικα αυτο το παραθυρο που λεει "errors,warnings κλπ" ..λογικα κατι πατησα κι το εκλεισα , ξερετε πως να το ξανα ανοιξω? Βολευε πολυ


Title: Re: [Δομημένος Προγραμματισμός] Άσκηση 5 (Hμ/νία λήξης: 10/4/2016)
Post by: Vlassis on March 31, 2016, 22:03:21 pm
Παιδες , εγω εχω αλλο προβλημα
Ενω παταω compile, και μου βγαζει αυτο το κοκκινο τετραγωνακι οτι υπαρχει λαθος ..δν μου βγαζει κατω απο τον κωδικα αυτο το παραθυρο που λεει "errors,warnings κλπ" ..λογικα κατι πατησα κι το εκλεισα , ξερετε πως να το ξανα ανοιξω? Βολευε πολυ
codeblocks εχεις;


Title: Re: [Δομημένος Προγραμματισμός] Άσκηση 5 (Hμ/νία λήξης: 10/4/2016)
Post by: leukosaraphs! on March 31, 2016, 22:04:40 pm
codeblocks εχεις;

Ναι , ξεχασα να το αναφερω ...


Title: Re: [Δομημένος Προγραμματισμός] Άσκηση 5 (Hμ/νία λήξης: 10/4/2016)
Post by: Apostolof on March 31, 2016, 22:04:55 pm
F2 πάτα τότε.


Title: Re: [Δομημένος Προγραμματισμός] Άσκηση 5 (Hμ/νία λήξης: 10/4/2016)
Post by: leukosaraphs! on March 31, 2016, 22:07:46 pm
F2 πάτα τότε.

Ωραιοςςςςς, και τωρα σχετικα με την ασκηση ..αν θελουμε να χρησιμοποιησουμε την συναρτηση pow ... pow(x, 3) πρεπει να κανουμε include την βιβλιοθηκη math.h? Το δοκιμασα και με αυτην και χωρις , κι δν ειδα καποιο warning ενω στο εργαστηριο μας ειπαν οτι αναγκαστικα πρεπει να την συμπεριλαβουμε


Title: Re: [Δομημένος Προγραμματισμός] Άσκηση 5 (Hμ/νία λήξης: 10/4/2016)
Post by: Egkelados on March 31, 2016, 22:09:35 pm
μπορείς να το κάνεις και με τους 2 τρόπους αλλά δεν ξέρω τι έχει διδάξει στη θεωρία ο dgen οπότε ο τρόπος του @Assassin είναι πιο "ασφαλής".


Title: Re: [Δομημένος Προγραμματισμός] Άσκηση 5 (Hμ/νία λήξης: 10/4/2016)
Post by: Apostolof on March 31, 2016, 22:20:18 pm

Δεν έχεις ενεργοποιημένα όλα τα warnings.

(http://s6.postimg.org/yz3kywwz5/Capture.gif)

Εξήγηση γιατί λειτουργεί χωρίς να δηλώσεις την math.h εδώ (http://stackoverflow.com/questions/977233/warning-incompatible-implicit-declaration-of-built-in-function-xyz).


Title: Re: [Δομημένος Προγραμματισμός] Άσκηση 5 (Hμ/νία λήξης: 10/4/2016)
Post by: leukosaraphs! on March 31, 2016, 22:43:17 pm
Μπερδευτηκα , δεν ηθελα να πω warnings , αλλα errors ... Αλλα οκ με καλυψε το link

Επισης @Egkelados δεν παταω στον dgen αρα δν ξερω τι οδηγιες εδωσε  :D :D


Title: Re: [Δομημένος Προγραμματισμός] Άσκηση 5 (Hμ/νία λήξης: 10/4/2016)
Post by: Egkelados on March 31, 2016, 22:45:03 pm
Επισης @Egkelados δεν παταω στον dgen αρα δν ξερω τι οδηγιες εδωσε  :D :D

χαχαχαχα γιατί ποιος πατάει;;;;;  :D  ;D  :D  ;D


Title: Re: [Δομημένος Προγραμματισμός] Άσκηση 5 (Hμ/νία λήξης: 10/4/2016)
Post by: kongr45gpen on March 31, 2016, 22:45:16 pm
Πολύ καλός Assassin. Σωστότατος και open source :)
Βέβαια καλό θα είναι αν έχεις έτοιμο πρόγραμμα που λειτουργεί και όχι απορίες να το ποστάρεις μετά τη λήξη της διορίας.

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

Σχετικά με το χρόνο εκτέλεσης μπορούμε να δούμε τα αποτελέσματα αυτού:
Code:
#include <stdio.h>
#include <time.h>
#define REP 1000000

double kybos1(float);
double ginomeno1(float,float,float);
double kybos2(float);
double ginomeno2(float,float,float);

int main() {
clock_t begin1, end1,begin2, end2;
double time_spent1,time_spent2;
float x,y,z;
double fu;
int i;
begin1 = clock();
for(i=0;i<REP;i++){
    x=y=z=i;
    printf("To αποτελεσμα της f(x) είναι : %f\n",kybos1(x)+ginomeno1(x,y,z) );
}
end1 = clock();
time_spent1 = (double)(end1 - begin1) / CLOCKS_PER_SEC;
begin2 = clock();
for(i=0;i<REP;i++){
    x=y=z=i;
    fu=kybos2(x)+ginomeno2(x,y,z);
    printf("To αποτελεσμα της f(x) είναι : %f\n",fu );
}
end2 = clock();
time_spent2 = (double)(end2 - begin2) / CLOCKS_PER_SEC;
printf("Time 1 = %lf\nTime 2 = %lf",time_spent1,time_spent2);
return 0;
}
double kybos1(float x){
return x*x*x;
}
double ginomeno1(float x, float y, float z){
return x*y*z;
}
double kybos2(float x){
double t;
t=x*x*x;
return t;
}
double ginomeno2(float x, float y, float z){
double t;
t=x*y*z;
return t;
}

Εγώ το έτρεξα μέχρι τις 1000000 επαναλήψεις και έβγαλε:
Code:
Time 1 = 165.24
Time 2 = 164.69

Δηλαδή η γραφή του Assassin είναι γρηγορότερη! Αυτό υποθέτω ότι συμβαίνει γιατί ο compiler που χρησιμοποίησα (mingw) κάνει καλύτερο optimization στη μορφή που το έχει γράψει ο Assassin από ότι στην άλλη. Ο ίδιος κώδικας όταν χρησιμοποίησα gnu gcc έδωσε:
Code:
Time 1 = 160.23
Time 2 = 160.26
Αν κάποιος ξέρει περισσότερα ας συμπληρώσει.

Συμφωνώ με Apostolof, το απλό return x*x*x φαίνεται πιο ευανάγνωστο, ενώ η άλλη λύση μπορεί να αυξήσει τις απαιτήσεις σε χώρο και μνήμη, αν και πάλι είναι αμελητέες.

Έκανα κι εγώ κάποια benchmarks με το GCC και τον κώδικα του Apostolof, αφού αφαίρεσα τις printf που είναι αρκετά βαριές (https://gist.github.com/kongr45gpen/269d32cafc307b6bce44d9ffd0856ed0). Με full optimization, οι δύο τρόποι δεν είχαν διαφορά (άλλοτε έβγαινε το 1 γρηγορότερο, άλλοτε το 2), ενώ με καθόλου optimization, οι συναρτήσεις χωρίς έξτρα μεταβλητή είναι ελάχιστα πιο γρήγορες από τις άλλες:

Code:
gcc -03

Time 1 = 0.282369
Time 2 = 0.282341

Code:
gcc -00

Time 1 = 2.374460
Time 2 = 2.612350

EDIT: gcc -O4gcc -O3