Primo, tu n'ira pas loin si tu ne dispose que de la notion de variable et, secundo, il n'est pas non plus question d'en arriver à un chapitre de dix pages expliquer ce qu'est une variable: une définition de un ou deux paragraphes (grand maximum) peut s'avérer amplement suffisant pour permettre à l'étudiant d'en comprendre la notion ou le concept.
Cela ne devrait pas prendre plus que l'équivalent d'une définition de dictionnaire, éventuellement, avec un (petit) paragraphe pour expliquer dans quel cas on devra y recourir.
Sur ce point au moins, nous sommes bien d'accordPour ce qui est d'apprendre Le C avant le C++ pour mieux comprendre ce dernier est une hérésie. Soit on fait du C ou soit on fait du C++.
Pour le débutant qui veut apprendre le C++ il est nullement besoin et surtout préférable de ne pas apprendre le C en préalable
C++ compte quand même parmi les langages les plus complexes à maîtriser, il ne faut pas l'oublier.Le C++ est un langage à part entière, il est facile
Soit, mais le début, c'est quoi, pour toi le Helo worldil faut juste être serieux et persevérent et commencer depuis le début sans se hâter à passer au chapitre suivant si certains détails non pas été compris. .
Et perdre un temps bête à tester des choses que tu n'aurais sans doute jamais essayées si tu avais pris le temps de respirer un bon coup avant de te jeter sur ton clavier.Au fur et à mesure de l'avancer dans un chapitre mettre immédiatement en pratique les choses vues. En somme il faut être avec le livre devant son compilateur et bosser. Ecrire, écrire encore écrire des centaines de lignes de code tester différent cas de figure pour un même problème, etc... voilà la clé de la réussite en programmation.
Tous les grands hommes ont dit leur lot de bêtises...Brian Kernighan inventeur du C a dit cela : "Programming is learned writing programs." (Apprendre à programmer c'est écrire du code).
Bien sur, la "pratique" est indispensable, mais la pratique d'un langage particulier est plus handicapante qu'autre chose en phase d'apprentissage.
Je ne dis pas qu'il ne faut pas s'entrainer, mais il faut, avant tout, s'entrainer à trouver la "bonne" logique (ou, à défaut, la logique la moins mauvaise) pour résoudre le cas auquel on est confronté.
Sais tu que la norme (version 2003) fait près de 800 pages Sais tu que la première phrase de la norme dit qu'il faut aussi se baser sur la norme C ISO/IEC 9899:1990 qui en fait à peut près autant
Combien de temps te faudra-t-il pour assimiler ces quelque 1600 pages et arriver à mettre correctement en oeuvre leur contenu
Je lis généralement très vite, et je peux lire un roman de 800 pages en deux jours si j'ai le temps à y consacrer (une semaine si je n'ai qu'une heure par jour )
Mais, même si je me souviendrai surement de certains passages particuliers, la compréhension que j'en aurai est sans aucune mesure avec la compréhension qu'il faut avoir d'un langage de programmation pour pouvoir estimer qu'on "le maitrise", ou même seulement qu'on le "connait parfaitement".
J'utilise C++ quotidiennement depuis 2004, et je considère que je suis très compétant dans ce langage: je pourrais presque dire, sans me vanter, que je maitrise "une bonne partie" du langage, et, pourtant, j'apprends encore des particularités et des détails dessus tous les jours...
Combien de temps serais tu près à accepter qu'un étudiant pratique par "essais successifs" pour arriver au résultat donné, à l'extrême limite sans savoir comment il y est arrivé
Ca, c'est le problème que tu as à résoudre, c'est déjà un bon départ, mais c'est loin d'être suffisant:Par contre il est nécessaire à la place de l'algorithmie de définir sur un papier le problème que l'on veut traiter. Comme par exemple :
Problème :
Invite l'utilisateur à saisir trois valeurs correspondant
respectivement a l'operation(+, -, *, /)
operande et suivi du deuxieme operande.
Puis affiche le resultat de l'operation sous la forme ( "2 + 2 = 4").
Si l'operation est inconnue un message indiquant l'erreur
s'affichera.
Je suis d'accord avec le fait que l'affichage d'un texte en C++ se fait avec cout.et voilà la solution (code) :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 #include <iostream> #include <string> using namespace std; int main() { cout << "-------------------------------------------------------------------------\n"; cout << "Program :\n\n"; cout << "\tInvite l'utilisateur a saisir trois valeurs correspondant\n"; cout << "\trespectivement a l'operation(+, -, *, /) suivi du premier\n"; cout << "\toperande et suivi du deuxieme operande.\n"; cout << "\tPuis affiche le resultat de l'operation sous forme ("2 + 2 = 4").\n"; cout << "\tSi l'operation est inconnue un message indiquant l'erreur\n"; cout << "\ts'affichera.\n"; cout << "-------------------------------------------------------------------------\n\n"; cout << "Choisissez une operation (+, -, *, /) : "; string str1; cin >> str1; cout << "Entrez deux nombres : "; double op1; cin >> op1; double op2; cin >> op2; //Insère une ligne vierge. cout << '\n'; //Affiche l'opération et son résultat demandés. if(str1 == "+") cout << op1 << " + " << op2 << " = " << op1+op2; else if(str1 == "-") cout << op1 << " - " << op2 << " = " << op1-op2; else if(str1 == "*") cout << op1 << " * " << op2 << " = " << op1*op2; else if(str1 == "/") cout << op1 << " / " << op2 << " = " << op1/op2; else //Si l'opération ne correspond pas à l'une des quatres oprérations //de base, l'ordinateur annonce à l'utilisateur qu'il ne la connaît pas. cout << "Je ne connais pas cette operation !"; system("pause"); return 0; }
Mais il faut comprendre le fait que ce soit cout en C++, printf en C, echo en PHP, printl en java ou en C# n'est jamais qu'un "détail" propre au langage.
De plus, et surtout, si tu y avais réfléchi un tout petit peu, tu aurais sans doute trouvé une solution bien plus facile à mettre en oeuvre et surtout plus "ergonomique".
Si tu y avais réfléchi un tout petit peu, tu en serais arrivé à la conclusion que le plus facile pour l'utilisateur était, définitivement, de lui demander d'introduire l'opération complète d'une seule traite (justement sous la forme de 2 + 2).
Tu en aurais donc déduit que l'introduction pouvait se faire de deux manières différentes:Dans le premier cas, tu as directement tout ce qu'il te faut pour travailler, mais tu cours le risque que le programme ne résiste pas au "test du singe" (quid si l'utilisateur introduit azerty au lieu d'une valeur numérique )
- soit tu lui fais "entièrement confiance" et tu récupère directement le premier opérande suivi de l'opérateur et enfin le deuxième opérande
- Soit tu ne lui fais pas confiance et tu commence par récupérer... une chaine de caractères représentant l'opération complète
Dans le second cas, il faut analyser la chaine de caractères obtenue afin de récupérer les deux opérandes et l'opérateur, de préférence en te donnant la possibilité de repérer les erreurs.
Une fois que tu as les deux opérandes et l'opérateur, qui tient sur un caractère ou sur une valeur numérique (ce qui revient, en définitive au même ), il est beaucoup plus intéressant d'utiliser un test à choix multiple plutôt qu'une succession de if ... else if:
Cela rendra ton code bien plus lisible et, vraisemblablement, plus rapide à l'exécution.
Enfin, si tu avais eu un minimum de théorie, tu aurais su qu'il n'est jamais bon de répéter du code, or, tu prévois ici quatre opérateurs différents et tu occasionne... quatre écritures quasi identiques qui ne varient justement qu'au niveau des opérateurs.
Si tu avais donc pris la peine de réfléchir un tout petit peu à l'algorithme à utiliser, tu en serais sans doute arrivé à quelque chose proche de (en pseudo code, car c'est ce qui passe le mieux sur un forum, mais je veux bien tracer un nassichneiderman si ca intéresse quelqu'un )
(1) j'ai pris ici la première solution exposée pour récupérer l'opération, alors que la deuxième aurait largement été préférable
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 afficher "Veuillez introduire votre opération" attendre operande1 operateur operande2 (1) si pas (operateur = '/' et operateur2 = 0) resultat = 0 selon operateur cas '+': resultat = operande1 + operande2 cas '-' : resultat = operande1 - operande2 cas '*' resultat = operande1 * operande2 cas '/' : resultat = operande1 / operande2 fin selon si operateur = '+' ou operateur = '-' ou operateur = '*' ou operateur = '/' afficher operande1 operateur operande2 "=" resultat sinon afficher "operation non prevue" fin si sinon afficher "attention : division par 0" fin si
Le code C++ aurait alors été proche de
[quote]
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 #include <iostream> int main() { double operande1; double operande2; char operateur; std::cout<<"Veuillez introduire votre opération"; std::cin>>operande1>> operateur>>operande2; if(!(operateur = ='/' et operateur2 == 0)) { double resultat = 0; switch(operateur) { case '+': resultat = operande1 + operande2; break; case '-': resultat = operande1 - operande2; break; case '*' : resultat = operande1 * operande2; break; case '/': resultat = operande1 / operande2; } if (operateur == '+' || operateur == '-' || operateur == '*' || operateur == '/') std::cout<<operande1 << operateur << operande2 <<"=" <<resultat<<std::endl; else { std::cout<<"operation non prevue"; } } else std::cout<<"attention : division par 0"; return 0; }
Idéalement, même si je ne remettrai pas le pseudo code, le code C++ devrait ressembler (pour résister au test du singe) à
C'est, certes, perfectible, mais c'est un premier jet alors que je rentre à peine
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 #include <iostream> #include <sstream> #include <string> int main() { std::cout<<"Veuillez introduire votre opération"; std::string operation; std::getline(std::cin, operation); std::stringstream ss; ss<<operation; double operande1; double operande2; char operateur; if(!ss>>operateur1) { cout<<"la valeur du premier opérande est incorrecte"; return 1; } ss>>operateur; if(!(operateur == '+' || operateur == '-' || operateur == '*' || operateur =='/')) { std::cout<<"l'opérateur est inconnu"; return 1; } if(!ss>>operande2) { cout<<"la valeur du deuxième opérande est incorrecte"; return 1; } if(!(operateur = ='/' et operateur2 == 0)) { double resultat = 0; switch(operateur) { case '+': resultat = operande1 + operande2; break; case '-': resultat = operande1 - operande2; break; case '*' : resultat = operande1 * operande2; break; case '/': resultat = operande1 / operande2; } if (operateur == '+' || operateur == '-' || operateur == '*' || operateur == '/') std::cout<<operande1 << operateur << operande2 <<"=" <<resultat<<std::endl; else { std::cout<<"operation non prevue"; } } else std::cout<<"attention : division par 0"; return 0; }
Le plus marrant de l'histoire, c'est que grâce à mon pseudo code, il serait tout à fait possible d'obtenir un résultat strictement identique en C, en java, en COBOL ou même en PHP (qui, malgré tout, peut s'exécuter sans une console )
Ta manière de programmer est tout sauf efficace.Voilà une manière efficace de programmer, je ne suis donc pas partisan de l'algorithmie.
La preuve: j'ai trouvé à redire finalement beaucoup de choses pour un problème aussi simple que celui que tu présentais
Tu sembles réfléchir "au coup par coup" à ce qui doit être fait après chaque opération que tu viens d'écrire, avec la conséquence que tu n'a aucune "vision d'ensemble" de ce qui doit être fait.
Si j'ai déjà eu tant à redire sur ton code avec un exemple si simple, imagine le résultat lorsque tu arrivera avec un problème nécessitant ne serait-ce qu'une dizaine de fonction et quatre structures.
Et pourtant, un tel programme reste encore dans la catégorie de ceux que l'on peut qualifier de simple
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
Coder efficacement en C++ : dans les bacs le 17 février 2014
mon tout nouveau blog
Pour répondre à koala01 au sujet de mes deux articles, je suis d'accord avec toi que je n'ai pas trop réfléchi au code de j'ai écris étant donnée que je l'ai écrit à la volée afin de démontrer la résolution du problème posé en langage humain, c'était juste un exemple.
Je ne pensais pas que tu allais prendre à coeur l'opération comando contre ce petit programme qui ne sert je le redis que d'exemple. Il y a bien évidement meilleur choix.
L'algorithmie je suis d'accord est importante pour les mathématiques mais de là à l'utiliser systématiquement pour écrire des programmes je reste perplexe.
Pour résoudre des problèmes mathématiques en programmation je suis d'accord que l'algorithmie ne sert pas à rien.
Mais honêtement pour écrire un programme qui ne nécessite aucune opération mathématique importante je doute fort que cela soit utile.
Ecrire un algo sur une feuille puis le transposer en code source je le répète est une perte de temps.
Par exemple le problème suivant :
Quel est votre et je vous dirai de quelle catégorie de gens vous faites partie.
et la solution est (sans algo. et à la volée) :
Cela est juste une démonstration simple de ce que je dis.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 #include <iostream> using namespace std; int main() { cout << "Veuillez saisir votre age : "; int age; cin >> age; if(age < 20 && age > 12) cout << "Vous ete un ado.\n"; else if(age < 13) cout << "Vous ete un enfant.\n"; else cout << "Vous ete un adulte.\n"; system("pause"); return 0; }
Je le répète c'est juste un exemple. Il est nullement besoin d'écrie une thèse scientifique sur ce code afin de le démonter.
Mais écrire sur papier tout un projet (cahier des charges) est nécessaire, mais l'algorithmie systématique pour tout code j'en doute...
Le bonheur est sans raison
Pensez-vous qu'écrire du pseudo-code comme celui-là est nécessaire :
Variables Mot1, Mot2, Mot3 en chaîne
debut
Mot1 <- "Hello"
Mot2 <- " world.
Mot3 <- Mot1 + Mot2
Fin
Ecrire
debut
Mot3
Fin
Ecrire un algo pour ce genre de prog. est lourd alors que l'écrire à la volée est plus profitable.
string Mot1 = "Hello";
string Mot2 = " world.";
string Mot3 = Mot1 + Mot2;
cout << Mot3;
Faut-il rééllement un algo pour ce genre de prog.
Le bonheur est sans raison
Cela tombe bien, j'ai moi aussi tout écrit à la volée (l'algorithme et les deux codes).
C'est d'ailleurs la raison pour laquell j'ai spécifié que le tout était surement perfectible .
L'ensemble de ma prose ne m'a pas demandé plus de vingt minutes, et pourtant, je suis assez fatigué ce soir.
L'exemple que tu montre est, justement, typique de ce que les débutants devraient réaliser le plus tôt possible:
Lorsqu'il y a "un problème à résoudre" en informatique, il faut réellement appliquer tout un processus pour s'assurer que le produit que l'on fournira au final rencontre les besoins effectivement énoncés (et, surtout, ceux qui sont restés plus ou moins implicite) en apportant autant de sécurité que possible.
Et pourtant...L'algorithmie je suis d'accord est importante pour les mathématiques mais de là à l'utiliser systématiquement pour écrire des programmes je reste perplexe.
Pour résoudre des problèmes mathématiques en programmation je suis d'accord que l'algorithmie ne sert pas à rien.
Mais honêtement pour écrire un programme qui ne nécessite aucune opération mathématique importante je doute fort que cela soit utile.
Ecrire un algo sur une feuille puis le transposer en code source je le répète est une perte de temps.
Il est vraiment important de comprendre qu'un langage de programmation (quel qu'il soit) n'est qu'un ensemble de conventions permettant de transmettre un message au processeur.
Ce message n'est rien d'autre que la logique selon laquelle les informations doivent être traitées.
Si, dans la transmission du message, tu en viens à inverser ne serait-ce que deux étapes, c'est l'ensemble du message qui risque de s'écrouler "comme un château de cartes" avec comme conséquence prévisible l'obtention d'un résultat totalement aberrant, dans le meilleur des cas.
Ce n'est même pas limité aux opération mathématiques, mais, essaye de lire dans un fichier avant de l'avoir ouvert (ou juste après l'avoir fermé) ou d'accéder à une variable que tu as explicitement détruite deux instructions auparavant, et tu comprendra ta douleur!!!
L'écriture d'un programme, quel qu'il soit, s'apparente grandement à l'écriture (et j'insiste: à l'écriture non à l'exécution) d'une recette de cuisine.
Si tu écris une recette de cuisine pour une sauce qui nécessite de faire fondre des oignons et que tu écris de les incorporer dans "la masse de la sauce" après les avoir coupés, mais sans les avoir fait fondre, le cuistot n'obtiendra jamais le résultat voulu.
En programmation, c'est exactement pareil...
Sans algo, soit, mais tu avouera quand même que le problème n'est pas particulièrement intéressant à résoudre...Par exemple le problème suivant :
Quel est votre et je vous dirai de quelle catégorie de gens vous faites partie.
et la solution est (sans algo. et à la volée) :
Cela est juste une démonstration simple de ce que je dis.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 #include <iostream> using namespace std; int main() { cout << "Veuillez saisir votre age : "; int age; cin >> age; if(age < 20 && age > 12) cout << "Vous ete un ado.\n"; else if(age < 13) cout << "Vous ete un enfant.\n"; else cout << "Vous ete un adulte.\n"; system("pause"); return 0; }
Je le répète c'est juste un exemple. Il est nullement besoin d'écrie une thèse scientifique sur ce code afin de le démonter.
Mais écrire sur papier tout un projet (cahier des charges) est nécessaire, mais l'algorithmie systématique pour tout code j'en doute...
Si tu es si fort: résouds moi les tour de Hannoï à la volée et sans algorithme.
Il y a un piège, car ce problème se résoud en cinq lignes de code ou à peine plus, et pourtant, sans réfléchir, il faut connaitre l'algorithme par coeur
Je peux t'assurer qu'il n'y a strictement aucune opération mathématique complexe dans l'histoire
Ou à peine plus complexe, et utilisant effectivement beaucoup d'opérations mathématique: trouver la date exacte de pâques pour n'importe quelle année introduite entre 1800 et 2100.
Si tu veux des exemples qui te convaincront de l'utilité des algorithme, je peux t'en donner à la pelle, et pourtant, la grosse majorité tient sur moins de cinquante lignes de code
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
Coder efficacement en C++ : dans les bacs le 17 février 2014
mon tout nouveau blog
Bonjour,
Voilà un sujet qui divise mais est fort passionnant (je viens d'ailleurs de le découvrir et de le lire d'une traite ).
Je suis comme à mon habitude d'accord avec tout le monde, ou plutôt j'entrevois les raisonnements de chacun.
J'ai plutôt tendance à être d'accord avec koala01 et j'en suis venu (peut-être à tort) à me demander si les divergences de point de vue n'étaient pas un problème "générationnel" (le mot est peut-être fort, d'autant plus que je l'emploie sans connaître les âges respectifs des protagonistes).
Mais j'ai l'impression, qu'il y a d'un côté le point de vue de ceux qui ont appris à une époque où ce n'était pas à la portée de tous comme aujourd'hui, une époque aussi où plus une erreur est détectée tôt moins elle coûte (c'est toujours vrai aujourd'hui mais dans une moindre mesure grâce aux SVN entres autres).
D'un autre côté il y a la génération actuelle, où tout va vite, où c'est le "tout technologique" et où l'idée de prendre sa feuille, son crayon (et surtout sa gomme) hérisse les cheveux.
Note: c'est un brin caricatural mais ça illustre bien le propos
Ce qui m'a fait "tiquer" et inciter à apporter ma maigre contribution c'est ce passage que je "déterre" un peu:
Cela m'a fait penser à mon tout premier jour de formation, quand notre formateur (un type qui ne savait pas pondre 3 lignes de codes, mais qui repérait une erreur comme un chien renifleur ) nous a dit, alors qu'on s'attendait tous (ou seulement moi ) à pianoter rapidement, que les 3 premiers mois formation seraient quasiment sans machine.
Imaginez ma déconvenue, il faut dire que j'avais un pc dans les mains depuis mon enfance (d'abord sur un Schneider MC810, sans parler des TO7/70, MO5 et autre Amstrad) bref toujours les doigts dans le code, ça m'a changé et ce n'est certainement pas un tort, j'y ai découvert des choses plus ou moins utiles (du moins que peu connaissent aujourd'hui j'ai l'impression )
Du plus connu au moins connu:
- Merise (d'ailleurs j'ai toujours des soucis avec UML aujourd'hui )
- La méthode Faulle (pour la conception des diagrammes d'écran et de l'interaction évènementielle qui va avec - Wikipédia ne connait même pas, j'ai réussi à trouver ce lien pour ceux que ça intéresse fichier Word
- "Le Warnier" (comme on l'appelait )
Voilà un exemple de schéma, même si je l'ai appris un peu différemment (mais ils appèlent ça diagramme Warnier/Orr aussi)
Et c'est cette dernière qui m'a fait réagir, Jean-Dominique Warnier et ses travaux sur les systèmes d'information, parce qu'avant tout et c'est là que je voulait en venir, la théorie dont on parle ici, a plus à voir avec l'information que l'informatique à proprement parler.
Mettre en oeuvre la logique pour appréhender un problème, c'est du domaine de l'information, son "implémentation" (à défaut de trouver un autre terme) est du domaine de l'informatique (pas exclusivement d'ailleurs), et c'est d'ailleurs bien expliqué dans l'article:
- Les données d’un système constituent un ensemble dont l’étude se conduit par subdivision hiérarchique.
- L’organisation des traitements se déduit de la structure hiérarchique des données.
- Les rubriques à utiliser pour le traitement sont déterminées par l’étude des sorties (résultats demandés).
Bon, je ne sais pas si cela à pris le sens que je pensais au départ (j'aurais dû décrire la logique de ma pensée sur papier, au lieu de coder d'écrire directement ) mais ça fera toujours du grain à moudre
Cordialement !
Nous sommes tous plus ou moins geek : ce qui est inutile nous est parfaitement indispensable ( © Celira )
À quelle heure dormez-vous ?
Censément, quelqu'un de sensé est censé s'exprimer sensément.
@Chessmaster1966, je considère l'algorithmie comme nécessaire au moins pour avoir une idée des problèmes de complexités, des algos classiques pour des problèmes récurrents. Je pluere chaque fois qu'un de mes étudiants écrit un inverse de matrice pour résoudre un système linéaire ou ne sait pas que les graphes, bah oui, y a deja des algos de traversées correctes et qu'il a pas besoin de son spagethhi de if else, et que ecrire un algo en O(n) ets trjrs mieux que d'ecrire un en O(n²) et de le paralleliser.
Et ça, ca s'apprends pas tout seul et c'ets complétement orthogonale au langage.
Le problème n'est pas posé en "langage humain" : il est déjà décrit sous une forme séquentielle d'opérations élémentaires permettant d'arriver au résultat souhaité. Et ça, c'est justement ce qu'on appelle de l'algorithmique.
Si tu as décrit ton problème sous cette forme, c'est que tu connais déjà le paradigme impératif, que tu connais déjà les opérations élémentaires de ton langage et que tu as déjà envisagé les alternatives/options/exceptions qui peuvent survenir durant le déroulement du programme.
Bref, tu as fait une étape d'analyse et conception de ton problème, adaptée au langage que tu as choisi. Quelle que soit la façon dont tu t'y es pris (méthodique, instinctive, expérience) cette étape nécessite un savoir-faire supplémentaire à la simple connaissance du langage.
ALGORITHME (n.m.): Méthode complexe de résolution d'un problème simple.
Bonjour à tous
A mon avis, si les gens apprenaient dès le début que l'approche correcte, c'est "d'abord le crayon puis le clavier" plutôt que "directement le clavier et en cas de problème, le crayon", on aurait probablement beaucoup moins de débutant perdu sur ce forum.
Pour prendre un exemple récent sur une fonction split pour une string : aucun problème pour comprendre la syntaxe C++, par contre, ça ne fonctionner pas à cause d'une mauvaise compréhension de ce qu'il fallait faire.
Après ça dépend de son niveau et de la complexité de l'algorithme utilisé. Un enfant de 5 ans va devoir écrire son addition pour la résoudre alors que le lycéen va résoudre ses équations différentielles complexes de tête (ou pas ). Apprendre à un débutant qu'il faut directement taper son code sans passer par l'algorithmique, cela revient à dire que la programmation se réduit à la connaissance du vocabulaire et de la grammaire d'un langage... bof
Bonjour,
est-ce que tout le monde est d'accord avec ça?
ecrire un algo en O(n) ets trjrs mieux que d'ecrire un en O(n²) et de le paralleliser
"Never use brute force in fighting an exponential." (Andrei Alexandrescu)
Mes articles dont Conseils divers sur le C++
Une très bonne doc sur le C++ (en) Why linux is better (fr)
Je crois qu'il est plutôt dit qu'entre les choix
1. faire un algo séquentiel en O(n)
2. faire un algo parallèle en O(n^2)
le premier est préférable.
Mais j'ai peut-être mal compris.
Sinon,
Je n'ai pas d'exemple à porter de main dans l'immédiat (mais je peux chercher) mais j'imagine que ça peut se justifier dans 2 situations au moins :Bah oui, je vois pas où un algo en O(n²) serait préférable à un algo en O(n). Tu as des exemples ?
1. lorsque le coût de stockage du O(n) est très grande par rapport au O(n^2),
2. lorsque que O(n^2) est numériquement stable et que le O(n) ne l'est pas.
-------------------------------------------------------------------------------------
EDIT suite à EDIT de la réponse de Davidbrcz (message précédent) :
Sur une machine parallèle ayant un nombre suffisant de processeurs, pour n suffisamment grand, avec l'algo en O(n^2) scalable, ça me semble couler de source.Bah oui, je vois pas où un algo threadé en O(n²) serait préférable à un algo en O(n). Tu as des exemples ?
Exactement.
Il y a, en effet, de très nombreux cas dans lesquels la seule expression d'un problème en "langage humain" ne suffit pas pour te permettre de coder directement en étant sur de l'ordre dans lequel tu dois faire les choses.
L'expression des règles des tours de Hannoï en est un exemple:
Déplacer des disques de diamètres différents d'une tour de « départ » à une tour d'« arrivée » en passant par une tour « intermédiaire » et ceci en un minimum de coups, tout en respectant les règles suivantes :
- on ne peut déplacer plus d'un disque à la fois,
- on ne peut placer un disque que sur un autre disque plus grand que lui ou sur un emplacement vide.
(ces règles sont respectées dans la configuration de départ)
Ces règles sont simples et facile à comprendre, mais la résolution du problème passe quand même par un nombre de déplacement d'autant plus important qu'il y a de disques (il faut, pour être précis, 2^N-1 déplacements pour N disques ), ce qui fait que l'idée même de coder l'ensemble des déplacements de manière strictement séquentielle n'est absolument pas envisageable
Et, comme je l'ai dit plus haut, la solution tient en cinq ligne de code effectives.
Un autre exemple, beaucoup plus complexe dans son expression, tiré de mon examen d'algorithmie:
La situation: je travailles pour une grosse société multinationale qui a des succursales dans les principales villes de l'ensemble des pays sur les cinq continents.
On me fournit tous les mois un fichier reprenant le chiffre d'affaire journalier de ces succursales du mois écoulé, triés par continent, par pays, par ville, par succursales et par jour.
J'ai besoin d'une sortie me présentant le chiffre d'affaire mensuel total de chaque succursales, de chaque ville, de chaque pays et de chaque continent, ainsi bien sur que le total général. (ce problème présente ce qui s'appelle la "gestion de ruptures" )
La solution tient en... une cinquantaine de lignes à peu près et six boucles imbriqués, mais s'il ne prend pas la peine de réfléchir un tout petit peu à la logique qu'il faudra mettre en oeuvre, le développeur éprouvera un long moment de solitude
C'est exactement ma thèse, et ce pour quoi je plaide.
Maintenant, si le papier, le crayon et la gomme sont "électroniques", cela ne me dérange absolument pas
Très certainement, du point de vue des performances, l'algo en O(n) est très largement meilleur, dans toutes les situations.
J'ai toutefois du mal à imaginer semblables situations, mais elles pourraient effectivement se présenter.Je n'ai pas d'exemple à porter de main dans l'immédiat (mais je peux chercher) mais j'imagine que ça peut se justifier dans 2 situations au moins :
1. lorsque le coût de stockage du O(n) est très grande par rapport au O(n^2),
2. lorsque que O(n^2) est numériquement stable et que le O(n) ne l'est pas.
Cependant, un algorithme en O(n²) parallélisé ne prend réellement de sens que lorsque l'on peut exécuter tous les processus "en même temps" (on se comprend sur ce terme qui est mal choisi ), si l'on veut garder des temps d'exécutions raisonnables et plus ou moins équivalentes (car il faut compter également le cout du lancement des processus parallèles, qui est... inexistant quand il n'y a pas de parallélisation )par rapport à un algorithme en O(n) non parallélisé.
Et nous nous trouvons alors face à certaines limitations que nous ne pourrons pas contourner ne serait-ce que du propre fait du matériel sur lequel l'exécution a lieu: le nombre de processus qu'il est possible de lancer en même temps.
Le tout sans même compter l'impossibilité même dans laquelle on peut se trouver de paralléliser un processus ou les délais qui pourraient être occasionnés par la nécessité d'éviter certains type d'accès concurrents et les délais que cela occasionne.
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
Coder efficacement en C++ : dans les bacs le 17 février 2014
mon tout nouveau blog
Je pense qu'il faut prendre la remarque de Joël dans le cadre de la vitesse d'exécution, toute autre chose égale par ailleurs.
Si les autres critères ne sont pas identiques entre les deux algorithmes, effectivement le choix sera peut être différents, mais ce n'est pas le sens de la remarque ici.
Pour en revenir à ta question précédente :
Oui, dans l'ensemble je suis d'accord avec ça. Je rajouterais juste deux précisions (d'ailleurs totalement indépendantes du fait de paralléliser ou non l'algorithme) :Envoyé par Aleph69
- Il faut comparer ce qui est comparable : si la répartition des donnée à manipuler est particulière, il faut bien entendu prendre en compte la complexité des algorithmes dans cette situation particulière et pas forcément la complexité moyenne [1].
- Du fait des constantes intervennant dans la relation vitesse/taille des données, certains algorithmes avec une complexité élevée peuvent être plus performants que des algorithmes possédant une meilleure complexité sur des jeux de données de taille très, très réduite, mais ce n'est qu'une "abhération" locale.
[1] Typiquement, certains algorithmes de tri avec une complexité moyenne assez élevée sont meilleurs que d'autres algorithmes ayant une meilleur compléxité sur des ensembles quasiment triés.
L'algorithme de Strassen est un bon exemple d'algorithme moins complexe mais moin stable que l'algorithme classique de multiplication matricielle.J'ai toutefois du mal à imaginer semblables situations, mais elles pourraient effectivement se présenter.Je n'ai pas d'exemple à porter de main dans l'immédiat (mais je peux chercher) mais j'imagine que ça peut se justifier dans 2 situations au moins :
1. lorsque le coût de stockage du O(n) est très grande par rapport au O(n^2),
2. lorsque que O(n^2) est numériquement stable et que le O(n) ne l'est pas.
Entre O(n) et O(n^2) je n'ai pas encore trouvé mais je ne perds pas espoir!
J'aurais plutôt plaidé pour ces propositions (tjrs du point de vue des perfs uniquement) et en admettant que les constantes dans O(n) et O(n^2) sont assez sympas pour ne pas me faire mentir :Très certainement, du point de vue des performances, l'algo en O(n) est très largement meilleur, dans toutes les situations.
1. O(n) séquentiel est plus rapide que O(n^2) séquentiel;
2. si on parallélise O(n) et O(n^2) de la meilleure façon possible pour chacun, alors O(n) ne sera pas nécessairement plus rapide que O(n^2).
On est d'accord. C'est pour cela que j'avais supposé la scalabilité du O(n^2).Le tout sans même compter l'impossibilité même dans laquelle on peut se trouver de paralléliser un processus ou les délais qui pourraient être occasionnés par la nécessité d'éviter certains type d'accès concurrents et les délais que cela occasionne
Pour mon exemple, c'est un exempel hein, vous voyez bien de quoi je parle
Bonsoir,
Bien sûr, c'était juste une petite remarque digressive!
D'ailleurs, pour vos étudiants qui inversent les matrices des systèmes linéaires, vous devriez leur conseiller la lecture du paragraphe 9.2.5. de ce livre.
Mais bon, on sort un peu du sujet.
Je suis bien d'accord avec vous pour dire que l'algorithmique est très importante.
Par contre, je ne pense pas qu'elle soit totalement orthogonale au langage de programmation (ex: parcours des coefficients d'une matrice dense en Fortran et en C).
Et n'oublions pas l'influence de l'architecture de la machine!
De façon générale, il me semble peu pédagogique d'enseigner une théorie sans pratique.
Qui a appris la linguistique avant sa première langue étrangère?
Qui a appris la logique mathématique avant d'avoir mener un seul raisonnement?
Pour la petite histoire, les grecs s'étaient déjà posé la question au temps de Platon.
Ils distinguaient deux formes de connaissance : l'une empirique, l'autre théorique.
Si mes souvenirs sont bons, Socrate discute de cela dans le Ménon.
Il pose la question suivante (à peu de choses près).
De qui diriez-vous qu'il connaît le chemin pour aller d'un point A à un point B?
Celui qui a déjà fait le trajet ou celui qui a regardé sur une carte?
Le fait est que le désaccord principal tient sur ce que l'on peut considérer comme étant déjà de la pratique.
Je considère personnellement que le simple fait de se confronter à un problème donné ( tel que ceux que j'ai cité en vitesse dans mon intervention précédente) et d'arriver à formaliser, de préférence sous la forme d'un algorithme la manière de les résoudre tient déjà de la pratique.
Et je ne peux qu'encourager tout le monde à se trouver un maximum de "problème à résoudre" pour chaque concept que l'on pourrait apprendre "de manière théorie".
Je ne donne toujours que mon avis personnel, mais, lorsque je conseille d'apprendre les principes généraux de base (propres à la programmation procédurale) "de manière indépendante de tout langage" je vise, essentiellement quelques définitions, méthodologie et un nombre assez restrient (bien que majoritaire) de concept.
Au total, on arrive à une petite vingtaine de points à aborder, dont il est même très facile de faire une liste exhaustive, mais non triée:
On pourrait, bien évidemment, dresser tout aussi facilement les listes exhaustives de points que l'on pourrait qualifier de "principes de base" pour le paradigme OO, le paradigme générique, la conception de base de données, etc
- lce qu'est une variable (définition)
- ce qu'est un type de donnée(définition)
- les types de données utilisateur (structure / union / autre) (définition / concept)
- les fonctions et les procédures (définition / concept)
- les tests "vrai / faux (concept)
- les tests "à choix multiple" (concept)
- les boucles"itératives" ("pour" ou "pour tout") (concept)
- les boucles "jusque" (concept)
- lles boucles "tant que" (concept)
- les tableaux (concept)
- la pile en tant que structure dynamique(concept)
- la file en tant que structure dynamique (concept)
- la liste simplement chainée / doublement chainée / circulaire (concept)
- les arbres binaires (concept)
- la récursivité (méthodologie)
- le pseudo code (méthodologie)
- le flow chart, même s'il est inadapté aux langages de troisième génération (méthodologie)
- le nassi-schneiderman (méthodologie)
- le Jackson (méthodologie)
Il me semble tout à fait évident que les explications sur ces méthodologie, ces définitions ou ces concepts devraient être immédiatement suivies de "mise ne situation".
Mais, encore une fois, il n'est absolument pas nécessaire de passer par un langage quelconque et le simple fait de demander de nous sortir un algorithme capable de rejoindre des besoins clairement indiqués "sur papier" peut parfaitement être considéré comme "passer à la pratique":
Si l'étudiant fournit un algorithme "qui tient la route" même (et surtout) quand il joue à "se prendre pour le processeur", parce que le fait de fournir un code source en n'importe quel langage de programmation ne revient jamais qu'à ... "changer les conventions de transmission de la logique envisagée".
Une fois que cette petite vingtaine de points a été abordée et que l'étudiant est capable de les formaliser dans un algorithme, quelle que soit la représentation envisagée, l'apprentissage d'un langage, d'un SGBDR ou d'une technologie quelconque correspondante passera "comme une lettre à la poste" car il suffira de donner "une table de conversion" reprenant la syntaxe, la grammaire, et les éventuels cas particuliers.
Je sais bien que rien ne remplace la pratique, et je ne dis absolument pas qu'il faut y renoncer.
Je dis juste qu'il y a plusieurs acceptions du terme à envisager
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
Coder efficacement en C++ : dans les bacs le 17 février 2014
mon tout nouveau blog
Bien au contraire...
Il "suffit" que l'étudiant se mette à la place du compilateur et à parler tout haut:C'est à la limite plus facile et surement plus sympa (parce que plus susceptible de faire rire l'étudiant) que d'utiliser le débuggeur, et finalement même sans doute plus rapide .Variable vaut 0
Tant que variable ne vaut pas 10 : quelle est la valeur de variable
ben on vient de dire qu'elle vaut 0, ce n'est pas 10, je rentre dans la boucle
je dois faire ceci (questions/ réponses)
j'incrémente variable
Est-ce que variable vaut 10
Non, on vient de dire qu'elle vaut 1... tu ne suis décidément pas...
On retourne donc dans la boucle
et ainsi de suite
Et il ne faut jamais sous-estimer le pouvoir du rire dans l'apprentissage: on retient beaucoup mieux ce que l'on a cherché par soi-même et ce à quoi on peut relier une anecdote
A méditer: La solution la plus simple est toujours la moins compliquée
Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
Compiler Gcc sous windows avec MinGW
Coder efficacement en C++ : dans les bacs le 17 février 2014
mon tout nouveau blog
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager