IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

avec Java Discussion :

avis sur 2 codes


Sujet :

avec Java

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    sans
    Inscrit en
    Septembre 2015
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : sans

    Informations forums :
    Inscription : Septembre 2015
    Messages : 3
    Points : 1
    Points
    1
    Par défaut avis sur 2 codes
    Bonjour,

    Je me suis mis à Java depuis une semaine en regardant la série de vidéos Java pour débutant des teachers du net, à l'avant dernière vidéo ils proposent un petit challenge
    ; il s'agit de faire un programme qui donne les facteurs premiers d'un nombre.

    Tout d'abord j'aimerais avoir des avis de personnes qui ont l'habitude d'utiliser le Java, j'ai résolut le challenge mais en mettant l'incrémentation de mes boucles for non pas dans les parenthèses à coté mais dans le else, je voulait savoir si ça se fait ou si c'est "moche" ?

    voila mon 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
    import java.util.ArrayList;
    import java.util.Scanner;
     
    public class FacteursPremiers {
     
    	public static void main(String[] args) {
     
    		Scanner clavier = new Scanner(System.in);
    		ArrayList<Integer> result = new ArrayList<>();
    		int nbre;
     
    		System.out.print("Entrez un nombre : ");
    		nbre = clavier.nextInt();
     
    		if (nombrePremier(nbre) == true) {
    			result.add(nbre);
    		} else {
    			for (int i = 2; i < nbre;) {
    				if (nbre % i == 0) {
    					result.add(i);
    					nbre = nbre / i;
    					if (nombrePremier(nbre) == true) {
    						result.add(nbre);
    					}
    				} else {
    					i++;
    				}
     
    			}
    		}
    		clavier.close();
    		System.out.println(result);
    	}
     
    	static boolean nombrePremier(int n) {
     
    		int mod;
     
    		for (int i = 2; i < n;) {
    			mod = n % i;
    			if (mod == 0) {
    				return false;
    			} else {
    				i++;
    			}
    		}
    		return true;
    	}
     
    }

    Après dans les commentaires de la vidéo j'ai trouvé une autre solution, je l'ai testé, elle marche mais je comprend pas comment, si par exemple on entre un nombre premier (5 par exemple) comme valeur, il affiche bien 5 alors que les seul endroit ou il ajoute des valeurs à son ArrayList facteurPremier c'est dans le premier if de la boucle for et un 5 ne rempli même pas les conditions de ce if.

    Voila le 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
    import java.util.ArrayList;
    import java.util.Scanner;
     
    public class Challenge {
    	static Scanner clavier = new Scanner(System.in);
    	static ArrayList<Integer> FacteurPremier = new ArrayList<Integer>();
    	static boolean BreakMethod = false;
     
    	public static void main(String[] args) {
    		System.out.println("Entrer un nombre : ");
    		Integer nbre = clavier.nextInt();
    		CalculFacteurPremier(nbre);
    		System.out.println(FacteurPremier);
    	}
     
    	static void CalculFacteurPremier(int nbre) {
    		int i;
    		if (BreakMethod) {
    			return;
    		}
    		if (nbre <= 1) {
    			BreakMethod = true;
    			return;
    		}
    		for (i = 2; i <= nbre; i++) {
    			if ((nbre % i) == 0) {
    				FacteurPremier.add(i);
    				if ((i * i) == nbre) {
    					FacteurPremier.add(i);
    					BreakMethod = true;
    				} else {
    					CalculFacteurPremier((nbre / i));
    				}
    				if (BreakMethod) {
    					return;
    				}
    			}
    		}
    	}
    }
    Vous avez l'explication ?

  2. #2
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Salut,

    Pour ta première question, on peut le faire (la syntaxe le permet), mais on le fait seulement quand on ne peut pas faire autrement, ou que ça simplifie le code. Par exemple, on pourrait faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    List<Integer> list = /* ... */
    for(int i=0;i<list.size(); ) {
       if (list.get()==0 ) {
           list.remove(); // on retire de la liste les éléments qui sont égaux à 0
       }
       else {
           i++; // on ne doit pas incrémenter i quand on supprime une valeur, sinon on va "sauter" l'élément suivant, donc on ne le fait que ici
       }
    }
    Et encore, on pourrait écrire ça différent, sans pour autant que ça soit très complexe, sans faire l'incrémentation en dehors du "for" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    List<Integer> list = /* ... */
    for(Iterator<Integer> iterator = list.iterator(); iterator.hasNext(); ) {
       if ( iterator.next()==0 ) {
            iterator.remove();
       }
    }
    En revanche, dans le cas de cette boucle :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    for (int i = 2; i < n;) {
        mod = n % i;
        if (mod == 0) {
           return false;
        } else {
           i++;
        }
    }
    Autant écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    for (int i = 2; i < n; i++) {
        mod = n % i;
        if (mod == 0) {
           return false;
        } 
    }
    Voire, mieux :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    static boolean nombrePremier(int n) {
     
       boolean nbPremier =true; 
       for (int i = 2; nbPremier && i < n;i++) {
    	int mod = n % i;
    	if (mod == 0) {
    	   nbPremier = false;
    	} 
       }
       return nbPremier;
    }
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    static boolean nombrePremier(int n) {
     
       boolean nbPremier =true; 
       for (int i = 2;  i < n;i++) {
    	int mod = n % i;
    	if (mod == 0) {
    	   nbPremier = false;
               break;
    	} 
       }
       return nbPremier;
    }
    Mais dans celle-ci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    for (int i = 2; i < nbre;) {
    				if (nbre % i == 0) {
    					result.add(i);
    					nbre = nbre / i;
    					if (nombrePremier(nbre) == true) {
    						result.add(nbre);
    					}
    				} else {
    					i++;
    				}
     
    			}
    C'est une erreur de ne pas le faire dans le for : si la condition if est vérifiée, on incrémente jamais i. Certes on "décrémente" nbre, mais il est très difficile de garantir au premier abord que la boucle n'est pas infinie. Même si certaines bidouilles peuvent avoir parfois un intérêt (performance en particulier), il vaut mieux privilégier la maintenance du code, car lorsqu'on revient sur un tel code des mois plus tard (pour corriger un bug par exemple, ou faire évoluer le code), on ne sait plus la plupart du temps quelle a été l'astuce utilisée. En plus, aucun test ne pourra être suffisamment exhaustif pour garantir la sortie systématique de la boucle (peut-être qu'on peut le démontrer mathématiquement pour le cas général, mais c'est tellement plus simple et clair de pouvoir en être sûr en lisant rapidement le code).

    L'autre code fait plus ou moins la même chose que toi, mais de manière récursive. En gros, toi tu fais :
    Code pseudocode : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    boucle 
       si machin est comme ça 
          machin devient un nouveau machin
       ...
    finboucle
    et l'autre code fait
    Code pseudocode : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    methodeTruc(machin) {
    ...
    si machin est comme ça
         appeler methodeTruc(nouveau machin)
    ...

    ce qui revient au même, on traite bien machin la première fois, et nouveau machin la suivante.

  3. #3
    Nouveau Candidat au Club
    Homme Profil pro
    sans
    Inscrit en
    Septembre 2015
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : sans

    Informations forums :
    Inscription : Septembre 2015
    Messages : 3
    Points : 1
    Points
    1
    Par défaut
    Merci beaucoup pour cette réponse super détaillée

    Par contre ici ...

    Citation Envoyé par joel.drigo Voir le message
    Mais dans celle-ci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    for (int i = 2; i < nbre;) {
    				if (nbre % i == 0) {
    					result.add(i);
    					nbre = nbre / i;
    					if (nombrePremier(nbre) == true) {
    						result.add(nbre);
    					}
    				} else {
    					i++;
    				}
     
    			}
    C'est une erreur de ne pas le faire dans le for : si la condition if est vérifiée, on incrémente jamais i. Certes on "décrémente" nbre, mais il est très difficile de garantir au premier abord que la boucle n'est pas infinie. Même si certaines bidouilles peuvent avoir parfois un intérêt (performance en particulier), il vaut mieux privilégier la maintenance du code, car lorsqu'on revient sur un tel code des mois plus tard (pour corriger un bug par exemple, ou faire évoluer le code), on ne sait plus la plupart du temps quelle a été l'astuce utilisée. En plus, aucun test ne pourra être suffisamment exhaustif pour garantir la sortie systématique de la boucle (peut-être qu'on peut le démontrer mathématiquement pour le cas général, mais c'est tellement plus simple et clair de pouvoir en être sûr en lisant rapidement le code).
    ... tu me dis que c'est une erreur de mettre l'incrémentation hors des parenthèses du for(), mais si je le fait pas comme ça j'ai pas le résultat voulu,
    par exemple si je veut les facteurs premiers de 100 il va me dire [ 2 , 5 ] au lieu de [ 2, 2, 5, 5] parce qu'au 2ème tour au lieu de tester 50 % 2 (50 parce que nbre(50) = nbre(100) /2) il va tester 50 % 3 ect...
    La boucle ne peut pas être infini parceque nbre est divisé par 2 à chaque tour si on incrémente pas donc forcement au bout d'un moment (rapidement même) nbre % 2 == 0 ne sera plus vrai.

  4. #4
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Ce que je voulais dire c'est qu'il y forcément une manière d'écrire cette boucle en ayant i++ dans le "for". Et c'est d'ailleurs la solution donnée dans le tutoriel (même si on pourrait des remarques négatives au sujet de cette solution). Au moins, on sait que la boucle est finie, et que la récursion a un condtion d'arrêt : on a pas besoin d'étudier le code pour être sûr que la boucle ne sera pas infinie.

  5. #5
    Nouveau Candidat au Club
    Homme Profil pro
    sans
    Inscrit en
    Septembre 2015
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : sans

    Informations forums :
    Inscription : Septembre 2015
    Messages : 3
    Points : 1
    Points
    1
    Par défaut
    Ok, je comprends, c'est une questions de lisibilité alors, merci beaucoup.

    Citation Envoyé par joel.drigo Voir le message
    Et c'est d'ailleurs la solution donnée dans le tutoriel
    Je vois pas ou est cette solution ?

    J'ai fait quelques modifs, c'est plus propre comme ça ?

    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
    import java.util.ArrayList;
    import java.util.Scanner;
     
    public class FacteursPremiers {
     
    	public static void main(String[] args) {
     
    		Scanner clavier = new Scanner(System.in);
    		ArrayList<Integer> result = new ArrayList<>();
    		int nbre;
     
    		System.out.print("Entrez un nombre : ");
    		nbre = clavier.nextInt();
     
    		do {
    			for (int i = 2; i < nbre; i++) {
    				if (nbre % i == 0) {
    					result.add(i);
    					nbre = nbre / i;
    					if (nombrePremier(nbre)==true){
    						result.add(nbre);
    					}
    					break;
    				}
    			}
    		} while (nombrePremier(nbre) != true);
     
    		clavier.close();
    		System.out.println(result);
    	}
     
    	static boolean nombrePremier(int n) {
     
    		int mod;
     
    		for (int i = 2; i < n; i++) {
    			mod = n % i;
    			if (mod == 0) {
    				return false;
    			}
    		}
    		return true;
    	}
     
    }

    EDIT :

    ou comme ça pour éviter d'appeler 2 fois nombrePremier et alléger un peu :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    do {
    	for (int i = 2; i < nbre; i++) {
    		if (nbre % i == 0) {
    			result.add(i);
    			nbre = nbre / i;
    			break;
    		}
    	}
    } while (nombrePremier(nbre) == false);
    result.add(nbre);

Discussions similaires

  1. [XHTML] Avis sur un code XHTML/CSS
    Par babyshambles76 dans le forum Balisage (X)HTML et validation W3C
    Réponses: 4
    Dernier message: 13/09/2007, 13h08
  2. Avis sur un code SDL
    Par Asmod_D dans le forum SDL
    Réponses: 3
    Dernier message: 18/02/2007, 22h33
  3. [FFT] Votre avis sur mon code
    Par deubelte dans le forum C++
    Réponses: 1
    Dernier message: 10/02/2007, 20h14
  4. [Code Prof]votre avis sur un code?
    Par granquet dans le forum Réseau
    Réponses: 6
    Dernier message: 11/04/2006, 20h41

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo