Bonsoir et meilleurs voeux pour l'annee 2024,
Y-a-t-il une limite au nombre de If ... Then...Else a l'interieur d'un Begin ... End.
Et si oui comment contourner la limite.
Merci d'avance pour le support.
Bien a vous
Bonsoir et meilleurs voeux pour l'annee 2024,
Y-a-t-il une limite au nombre de If ... Then...Else a l'interieur d'un Begin ... End.
Et si oui comment contourner la limite.
Merci d'avance pour le support.
Bien a vous
Bonjour et meilleurs voeux !
Il ne semble pas y avoir de limite au nombre de if...then...else imbriqués. Toutefois, il est généralement possible de remplacer des séries de if par d'autres instructions de contrôle comme le case...of.
Mais concrètement, pourrais-tu donner plus d'informations sur ce que tu veux faire ?
Bonjour,
Comme Alcatîz, je ne pense pas qu'il y ait de limites. Du moins pour le langage. Pour le développeur, c'est différent. Plus de 6 tests imbriqués en rend la lecture difficile et il est important (mais pas toujours possible) de ne pas trop dépasser cette limite.
Pour les test de de la forme if a... then ... else if a... then ... else if a... then ... else if a... then ... else if a..., le case est la solution déjà évoquée. D'autant qu'elle facilite les regroupements des cas ayant le même effet.
Pour les autres, il est souvent utile, en performances comme en lisibilité, d'équilibrer les tests comme on équilibre un arbre binaire pour qu'il ait une profondeur maxi qui n'excède pas plus de 1 la profondeur mini. Souvent plus difficiles à écrire, ils permettent de s'approcher de log2(n) tests exécutés pour n cas contre quelque chose qui peut tendre vers n/2 tests exécutés.
Par exemple avec n cas = 32, il est possible d'espérer une profondeur de 5 tests contre 31 (certes dans le pire des cas d'écriture) et 5 tests exécutés contre 16 (en moyenne).
Un autre avantage est que les performances des tests équilibrés sont quasiment insensibles à la répartition des cas alors qu'il faudra mettre les cas les plus probables en début des tests pour obtenir de bonnes performance dans une programmation plus linéaire.
Par ailleurs, certains tests qui entraînent la même conséquence, peuvent parfois être regroupés en un seul en utilisant une bonne connaissance des fonctions logiques (le xor par exemple).
Il peut être nécessaire de créer des variables intermédiaires pour simplifier les tests car il n'y aucun gain à calculer plusieurs fois une même sous-expression qui, en outre, alourdit l'écriture et la lecture du code.
Salutations
Tout d'abord merci Alcatiz et Guesset pour votre réponse.
Un petit mot d'explication sur ce que je souhaite faire.
J'essaye de construire un petit système expert qui si Cond1 est rempli du If Then exécutera Act1 et le Else est implicite non écrit, i.e. le programme continu son cours normal.
En consequence j'ai une série de 2000 ou plus de " If Cond1 Then " qui se suivent les uns a la suite des autres et donc je n'ai pas de If then Else imbriqués (ce que j'aurai du préciser dans mon message initial). Je ne pense pas que Le case of puisse être utilisé dans ce cas.
Et très curieusement quand je rajoute de nouveaux " If Then " le compilateur me sort des erreurs incompréhensibles a des endroits qui semblent completement aléatoires.
Pour m'en sortir, j'ai essayé de basculer sur la dernière version de Lazarus 3.0 mais la j'ai rencontré un pb de compatibilité. Quand j'exécute me pgm j'obtiens des résultats différents sous 3.0.
Je suis donc retourné a mon ancienne version de compilateur 1.6.4. La compatibilité ascendante apparemment n'est pas completement assurée...
Merci de m'éclairer sur la meilleure piste a suivre.
Salut
il n'y a pas de limite au if then sinon cela ferais longtemps que tout les programme ne fonctionnerais pas
par contre tu me fait peur quand tu me dis que tu en as 2000 qui se suivent mais bon a chacun sa façon de développer
le plus simple pour t'en convaincre serais de transformer toutes tes condition en méthode
je pense plus a une erreur dans tes méthodes appelé qu'a un problème de condition
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 Procedure ...Main; Begin ExecAct1(Cond1); ExecAct2(Cond2); .... ExecAct2000(Cond2000); End: Procedure ...ExecAct1(Cond1); Begin if Cond1 = 'MaCond' Then ACt1; End; ....
tu n'aurais pas des GOTO qui traine avec un label ou une boucle infinie
ou mieux encore un debordement de tableau dynamique
change les option de ton compilateur pour qu'il soit plus stricte ... tu aura peut etre ta solution
Bonjour Anapurna et merci pour ta réponse,
J'ai pensé aller dans ton sens car je peux segmenter mes 2000+ "If Then Act1 " en 80 procedures, l'appel des procedures se faisant de façon similaire a ta description.
Maintenant effectivement le "Act1 " représente un GOTO IDENTIQUE dans tous les cas. J'ai recours au "maudit" GOTO car je suis confronté a un pb de rapidité a l'exécution or quand la condition If au rang 200, est rempli, je ne veux pas avoir a executer les 1800 autres If restant. Peut être que mon code devrait etre revu, mais pour l'instant cette solution fonctionne bien.
Enfin au sujet des résultats degrades quand je passe de la version 1.6.4 a 3.0 de compilateur je souhaiterai preciser que je fais énormément de calculs utilisant le Type Float ou Real,
peut être que sous 3.0 la precision a été améliorée ? Quand pense tu ?
Merci pour l'aide.
salut
le GOTO n'est pas une bonne solution
Il y a toujours moyen de linéariser le code et au final ne pas perdre de tempsIF MACONDITION THEN
BEGIN
ACT1;
ACT2;
ACT3;
..
ACTN;
END
ELSE
BEGIN
ACTN;
END;
ACTFIN;
car le GOTO prend forcement plus de temps qu'une condition
le compilateur doit accéder a sa mémoire pour retrouver le label ...
PS : Quand as ton interrogation sur les float si tu ne dépasse pas la capacité de celui-ci cela ne devrais pas poser de problème
Tu comprendra qu'il nous est difficile de t'aider avec si peut d'information
Bonjour,
Non le goto n'est pas plus long qu'un test. A la compilation, les goto label sont transformés en jmp vers l'adresse correspondant au label. A l'exécution il n'y a plus de label, juste des sauts courts ou long selon la distance entre l'adresse courante et celle du point à joindre.
Dans le cas d'un test, il y a le calcul de l'expression en test et un saut conditionnel si le résultat est faux (jz ou je), dans le cas d'un test if then else il y a en plus un jmp pour, en fin de bloc then, sauter les instructions du bloc else.
Ceci ne serait pas valable pour les goto calculés du Fortran. Mais on change de monde.
Toujours est-il qu'il faudrait voir au moins une partie du code (et des messages d'erreurs) pour pouvoir éventuellement conseiller quelque chose. Faute de plus d'informations, j'ai l'impression, peut-être fausse, qu'il y a une machine à état derrière ce problème.
Salutation
il faut utiliser des structures en arborescences sinon vous allez tourner en rond rapidement; par exemple utiliser un arbre binaire avec lequel on construit des noeuds et des branches au fur et à mesure des conditions.
Chercher dans les tutos de ce forum il y a un tuto pour créer des arborescences.
Par exemple pour construire un système expert créer un noeud "chien" avec deux branches filles qui pointent donc sur deux noeuds "doberman","caniche" etc...
Sinon à ma connaissance il y a une bibliothèque d'IA qui peut faire la job
Merci pour la réponse Anapurna.
Pour répondre a ta demande d'info voici un bout de code
If (NO_OF_STEP = 2 ) and ( TCPH < 24 ) and ( ((CPDH-1)*100) < -10.61 ) and ( SSI4 < 1 ) and ( TCPL < 15 ) then Goto NTB;
If (NO_OF_STEP = 2 ) and ( TCPH < 24 ) and ( ((CPDH-1)*100) < - 8.73 ) and ( SSI4 < -0.86 ) and ( TCPL < 5.31 ) then Goto NTB;
If (NO_OF_STEP = 2 ) and ( TCPH < 6.46 ) and ( ((CPDH-1)*100) < - 7.77 ) and ( SSI4 < 0 ) and ( TCPL < 5.31 ) then Goto NTB;
If (NO_OF_STEP = 2 ) and ( TCPH < 6.46 ) and ( ((CPDH-1)*100) < - 7.06 ) and ( SSI4 < -0.61 ) and ( TCPL < 1.30 ) then Goto NTB;
If (NO_OF_STEP = 2 ) and ( TCPH < 6.16 ) and ( ((CPDH-1)*100) < - 4.38 ) and ( SSI4 < 0 ) and ( TCPL < 1.30 ) then Goto NTB;
If (NO_OF_STEP = 2 ) and ( TCPH < 6.16 ) and ( ((CPDH-1)*100) < - 3.71 ) and ( SSI4 < -0.37 ) and ( TCPL < 1.30 ) then Goto NTB;
If (NO_OF_STEP = 2 ) and ( TCPH < 6.16 ) and ( ((CPDH-1)*100) < - 3.39 ) and ( SSI4 < -0.37 ) and ( TCPL < 1.03 ) then Goto NTB;
If (NO_OF_STEP = 2 ) and ( TCPH < 2.63 ) and ( ((CPDH-1)*100) < - 3.02 ) and ( SSI4 < 0 ) and ( TCPL < 1.03 ) then Goto NTB;
If (NO_OF_STEP = 2 ) and ( TCPH < 2.63 ) and ( ((CPDH-1)*100) < - 2.29 ) and ( SSI4 < -0.95 ) and ( TCPL < 1.03 ) then Goto NTB;
If (NO_OF_STEP = 2 ) and ( TCPH < 2.63 ) and ( ((CPDH-1)*100) < - 2.05 ) and ( SSI4 < -0.95 ) and ( TCPL < - 2.03 ) then Goto NTB;
If (NO_OF_STEP = 2 ) and ( TCPH < 1.98 ) and ( ((CPDH-1)*100) < - 2.03 ) and ( SSI4 < 0 ) and ( TCPL < - 2.03 ) then Goto NTB;
"
(NO_OF_STEP peut varier de 1 a 80 et nous avons donc 2000+ " If Then Goto " de ce type.
Sur la base de cette information penses tu que la solution pour linéariser le code que tu me proposais soit adaptée?
Merci.
Bonjour,
Juste sur les quelques lignes de code, il est possible de proposer a minima :
C'est très loin d'être optimal mais dans le pire des cas on fait 12 comparaisons alors que l'écriture précédente en utilise 55. Dans un cas moyen, l'écriture proposée fait a peu près 8 tests là où l'originale en prend 28. Il y a donc un gain minimal de x3 accentué en précalculant CPDH*100-100 (une autre approche serait d'avoir des tests CPDH < 0.8939 qui vaut 1-10.61/100 pour le premier).
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 if NO_OF_STEP = 2 then begin C100 := CPDH*100-100; if TCPH < 1.98 then begin if (C < -2.03) and (SSI4 < 0 ) and (TCPL <-2.03) then Goto NTB; end else if TCPH < 2.63 then begin if ((C < -3.02) and (SSI4 < 0 ) and (TCPL < 1.03)) or ((C < -2.29) and (SSI4 < -0.95) and (TCPL < 1.03)) or ((C < -2.05) and (SSI4 < -0.95) and (TCPL <-2.03)) then Goto NTB; end else if TCPH < 6.16 then begin if ((C < -4.38) and (SSI4 < 0 ) and (TCPL < 1.30)) or ((C < -3.71) and (SSI4 < -0.37) and (TCPL < 1.30)) or ((C < -3.39) and (SSI4 < -0.37) and (TCPL < 1.03)) then Goto NTB; end else if TCPH < 6.46 then begin if ((C < -7.77) and (SSI4 < 0 ) and (TCPL < 5.31)) or ((C < -7.06) and (SSI4 < -0.61) and (TCPL < 1.30)) then Goto NTB; end else if TCPH < 24 then begin if ((C <-10.61) and (SSI4 < 1 ) and (TCPL < 15 )) or ((C < -8.73) and (SSI4 < -0.86) and (TCPL < 5.31)) then Goto NTB; end; end;
Il y a plein d'autres approches. La plus efficace nécessitera de tenir compte de la construction de tous ces seuils.
Remarque : j'ai supposé des cas disjoints, c'est à dire que, par exemple, le seuil TCPH < 24 supposait TCPH >= 6.46. Si ce n'est pas le cas il faudrait revoir cette écriture (ordre inversé et imbrication).
Salutations
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