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

Java Discussion :

Problème d'affectation de variable dans une boucle


Sujet :

Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2013
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2013
    Messages : 3
    Par défaut Problème d'affectation de variable dans une boucle
    Bonjour,

    Je débute en Java. Dans un cours, je dois créer un programme qui génère un nombre aléatoire entre 1 et 10 000. Chacun des chiffres de ce nombre doivent être en ordre croissant lorsqu'on les lit de gauche à droite. Si ce n'est pas le cas, le programme doit généré un autre nombre, jusqu'à ce que la condition précédente soit vraie.

    Jusqu'à présent, mon programme est capable de décortiquer chaque chiffres et de tous les mettre dans une variable différente sans problème. Il les affiche et les résultats sont bons. Cependant, le problème survient lorsque je tente de créer la condition de la boucle ( (c1 < c2) && (c2<c3) && (c3<c4) && (c4<c5) )

    J'arrive à aucun résultat ou le programme entre dans une boucle infini. Voilà le code. Merci à celui ou celle qui saura répondre !

    Code Java : 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
    double c1=0, c2=0, c3=0, c4=0, c5=0, nb=0;
             double i=0, i2=0, i3=0, i4=0, i5=0;
             double d1=0, d2=0, d3=0, d4=0, d5=0;
     
     
     
             do {
     
                 entierAleatoire9 = rnd.nextInt(10001);
                 System.out.println("L'entier généré est : " +entierAleatoire9);
                 nb = entierAleatoire9;
                 c1 = (nb/10000);
     
                 i = new Double(c1).intValue();
                 d1 = c1 - (new Double (i).doubleValue());
                 //System.out.println("décimale 1 = " +d1);
     
                 c1 = (int)d1;
     
                 i2 = new Double(c1).intValue();
                 d2 = (d1*10) - (new Double (i2*10).doubleValue());
                 //System.out.println("décimale 2 = " +d2);
     
                 c2 =(int)d2;
     
                 i3 = new Double(c2).intValue();
                 d3 = (d2*10) - (new Double (i3*10).doubleValue());
                 //System.out.println("décimale 3 = " +d3);
     
                 c3 =(int)d3;
     
                 i4 = new Double(c3).intValue();
                 d4 = (d3*10) - (new Double(i4*10).doubleValue());
                 //System.out.println("décimale 4 = " +d4);
     
                 c4 =(int)d4;
     
                 i5 = new Double(c4).intValue();
                 d5 = Math.rint((d4*10) - (new Double (i5*10).doubleValue()));
                 //System.out.println("décimale 5 = " +d5);
     
                 c5 = (int)d5;
     
     
             System.out.println("Les chiffres en ordres sont : " +c1 +"  " +c2+"  " +c3+"  " +c4+"  " +c5);  // Tout est parfait ici
     
             } while ((c1<=c2) && (c2<=c3) && (c3<=c4) && (c4<=c5)) ;    // Et tout va mal là !

  2. #2
    Membre actif
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    47
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 47
    Par défaut
    Citation Envoyé par gabbf29 Voir le message
    Bonjour,

    Je débute en Java. Dans un cours, je dois créer un programme qui génère un nombre aléatoire entre 1 et 10 000. Chacun des chiffres de ce nombre doivent être en ordre croissant lorsqu'on les lit de gauche à droite. Si ce n'est pas le cas, le programme doit généré un autre nombre, jusqu'à ce que la condition précédente soit vraie.

    Jusqu'à présent, mon programme est capable de décortiquer chaque chiffres et de tous les mettre dans une variable différente sans problème. Il les affiche et les résultats sont bons. Cependant, le problème survient lorsque je tente de créer la condition de la boucle ( (c1 < c2) && (c2<c3) && (c3<c4) && (c4<c5) )

    J'arrive à aucun résultat ou le programme entre dans une boucle infini. Voilà le code. Merci à celui ou celle qui saura répondre !

    Code Java : 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
    double c1=0, c2=0, c3=0, c4=0, c5=0, nb=0;
             double i=0, i2=0, i3=0, i4=0, i5=0;
             double d1=0, d2=0, d3=0, d4=0, d5=0;
     
     
     
             do {
     
                 entierAleatoire9 = rnd.nextInt(10001);
                 System.out.println("L'entier généré est : " +entierAleatoire9);
                 nb = entierAleatoire9;
                 c1 = (nb/10000);
     
                 i = new Double(c1).intValue();
                 d1 = c1 - (new Double (i).doubleValue());
                 //System.out.println("décimale 1 = " +d1);
     
                 c1 = (int)d1;
     
                 i2 = new Double(c1).intValue();
                 d2 = (d1*10) - (new Double (i2*10).doubleValue());
                 //System.out.println("décimale 2 = " +d2);
     
                 c2 =(int)d2;
     
                 i3 = new Double(c2).intValue();
                 d3 = (d2*10) - (new Double (i3*10).doubleValue());
                 //System.out.println("décimale 3 = " +d3);
     
                 c3 =(int)d3;
     
                 i4 = new Double(c3).intValue();
                 d4 = (d3*10) - (new Double(i4*10).doubleValue());
                 //System.out.println("décimale 4 = " +d4);
     
                 c4 =(int)d4;
     
                 i5 = new Double(c4).intValue();
                 d5 = Math.rint((d4*10) - (new Double (i5*10).doubleValue()));
                 //System.out.println("décimale 5 = " +d5);
     
                 c5 = (int)d5;
     
     
             System.out.println("Les chiffres en ordres sont : " +c1 +"  " +c2+"  " +c3+"  " +c4+"  " +c5);  // Tout est parfait ici
     
             } while ((c1<=c2) && (c2<=c3) && (c3<=c4) && (c4<=c5)) ;    // Et tout va mal là !
    Le problème viens du fait que la sortie de boucle c'est "si condition est false"
    donc avec (c1<=c2) && (c2<=c3) && (c3<=c4) && (c4<=c5) on sort de la boucle dès que l'une des conditions voulues est fausse. Il faut donc plutôt utiliser : !(c1<=c2 && c2<=c3 && c3<=c4 && c4<=c5)

    Rq: l'algorithme serait plus "élégant" en travaillant avec des int vus l'intervalle des valeurs.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    int valeur = (int)(Math.random() * 10000);
    int a=0,b=0,c=0,d=0,e=0;
    int valeur = (int) (Math.random() * 10000);
     
    a = valeur /10000;
    b = (valeur - 10000 * a) / 1000;
    c = (valeur - 10000 * a - 1000 * b) / 100;
    d = (valeur - 10000 * a - 1000 * b - 100 * c) / 10;
    e = valeur - 10000 * a - 1000 * b - 100 * c - 10 * d;

    il y a aussi la solution de tirer un nombre entre 0 et 9 compris. le numéro suivant devra être aussi supérieur ou égale au précédant en faisant une petite boucle dans une méthode genre :
    int numeroSuivant(int numeroPrecedant)

  3. #3
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    ouais enfin, avec le modulo on se casse pas la nenette et c'est encore plus lisible hein
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    Random r= new Random();
    int valeur = r.nextInt(10001);
     
    int a = valeur /10000;
    int b = (valeur %10000) / 1000;
    int c = (valeur %1000) / 100;
    int d = (valeur %100) / 10;
    int e = valeur %10;

  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 : 55
    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
    Billets dans le blog
    2
    Par défaut
    Au final, la fonction de génération devient donc (sur la base de la solution de @tchize_)

    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
    private static Random random = new Random();
    public static int genere() {
     
       while(true) { 
          int valeur = 1 + random.nextInt(10000); // nombre entre 1 et 10000 inclus
          int a = valeur /10000;
          int b = (valeur %10000) / 1000;
          if ( a!=0 && b<=a ) continue;
          int c = (valeur %1000) / 100;
          if ( b!=0 && c<=b ) continue;
          int d = (valeur %100) / 10;
          if ( c!=0 && d<=c ) continue;
          int e = valeur %10;  
          if ( d!=0 && e<=d ) continue;
          return valeur;
       }
     
    }
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  5. #5
    Membre émérite Avatar de JoeChip
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    536
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2008
    Messages : 536
    Par défaut
    A mon nain blavi :
    - le "while(true)" et les "continue", c'est forcément pas terrible d'un point de vue sémantique... Il faut toujours éviter ce genre de trucs, sauf si la performance est cruciale,ce qui n'est pas le cas ici. break et continue sont déstructurants, en général, donc sont toujours un signe qu'il faut regarder de plus près.
    - Même si c'était le cas, on pourrait optimiser d'autres choses avant.

    Donc, j'ai refactorisé à ma sauce, en mélangeant une meilleur sémantique et dans la boucle une meilleure optimisation (et accessoirement en passant tout en anglais):

    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
    private static Random random = new Random();
    public static int generate() {
       boolean notFound;
       do { 
          notFound = false;
          int value = 1 + random.nextInt(10000);
          int a = value /10000;
          int b = (value %10000) / 1000;
          if ( a!=0 && b<=a ) notFound = true;
          int a = value /1000;
          int b = (value %1000) / 100;
          int a = value /100;
          int b = (value %100) / 10;
          if ( a!=0 && b<=a ) notFound = true;
          int a = value /10;
          int b = (value %10);
          if ( b!=0 && a<=b ) notFound = true;
       }while (notFound);
       return value;
     
    }
    Mouais, pas terrible : on parcourt toute la boucle même quand on sait que la valeur ne correspondra pas. en plus ya toutes ces lignes qui n'arrêtent pas de se répéter ou presque, agaçant ça, en plus tous ces "a" et ces "b" qui intervertissent leur rôle c'est pas clair.
    On peut toujours déjà imbriquer les "if" si on veut améliorer la perf sans trop endommager la sémantique, même s'il est vrai que c'est pas terrible non plus, je préfère ça aux "continue". ... donc on commence par mettre ce qui se répète dans une fonction, puis on voit :
    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
    private static Random random = new Random();
    public static int generate() {
          boolean notGood(int value, int factor){
             int a = value/factor;
             int b = value %factor / (factor / 10) 
             return ( a!=0 && b<=a );
          }
       boolean notFound;
       do { 
          notFound = false;
          value = 1 + random.nextInt(10000);
          if notGood(value,10000) notFound = true;
          else if notGood(value,1000) notFound = true;
          else if notGood(value,100) notFound = true;
          else if notGood(value,10) notFound = true;
       }while (notFound);
    return value;
    Bon, on commence à voir clair ; maintenant il y a visiblement une boucle for pour générer les facteurs de 10... En en plus b est à lecture unique, dont plus ou moins inutile, et le "!=0" n'est utile que la première fois, donc a est aussi à usage unique, donc on se retrouve avec (erreurs de syntaxe corrigées, désolé je fais plutôt du Python ces temps-ci) :
    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
     
        private static Random random = new Random();
        static boolean notGood(int value, int factor){
            return (((10 * (value%factor)) / factor)<=(value/factor));
        }
        public static int generate() {
           final int [] factors = {10000, 1000, 100, 10};
           boolean notFound;
           int value;
           do { 
              notFound = false;
              value = 1 + random.nextInt(10000);
              if (value>12344)   // 12345 est le premier nombre obéissant à la condition
              for (int factor : factors)
                  if (notGood(value,factor)) notFound = true;
           }while (notFound);
           return value;
        }
    Là ça commence à être cool, lisible, compact, pas un mot de trop... Je n'exclus pas l'un ou l'autre bug dans ma refactorisation, et il y a peut-être trop de parenthèses dans la fonction, mais c'est le matin et on n'est jamais trop prudent. Et il est vrai qu'on peut préférer, pour la clarté de lecture, la version avec "a" et "b" (moi en général j'hésite, ça dépend de ce que je recherche comme perfs, par exemple). On continue de parcourir toute la boucle même quand on sait que ça ne sera pas bon, mais ça peut ne pas être important en terme de perfs, et ça peut même être utile de travailler à temps relativement constant. Ya encore moyen d'adapter, je ne dis pas que ce dernier code est le meilleur, hein.

  6. #6
    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 : 55
    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
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par JoeChip Voir le message
    - le "while(true)" et les "continue", c'est forcément pas terrible d'un point de vue sémantique...
    Il faut toujours éviter ce genre de trucs, sauf si la performance est cruciale,ce qui n'est pas le cas ici.

    ...
    d'adapter, je ne dis pas que ce dernier code est le meilleur, hein.
    Mouais, je ne débaterai pas ça ici. Pour moi c'est une question de point de vue justement, et pas vraiment sémantique.

    Après, sans chercher à savoir quelle solution est la meilleure sémantiquement, ou techniquement, ou du point de vue des performances, et sans évoquer les erreurs de syntaxes dans tous les sens (oups si finalement), je ne trouve pas qu'une boucle est forcément plus compréhensible (j'ai pensé à cette solution). Disons qu'une telle solution permettrait éventuellement plus facilement d'écrire une fonction plus générique, permettant de générer des nombres entre bornes quelconques.

    Enfin, si l'aspect performance n'est pas crucial, pourquoi tester le cas 12345 ?
    D'autant plus que tous les nombres <= 12344 étant tirés 9876 serait tiré, alors qu'il ne vérifie pas les conditions.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  7. #7
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Dommage que tous ces codes échouent sur

    1
    12
    123
    1234

    Pourtant, tous respectent la condition de départ ^^

Discussions similaires

  1. [Batch] problème d'affectation de variable dans boucle imbriquée
    Par fred_04510 dans le forum Scripts/Batch
    Réponses: 2
    Dernier message: 04/02/2012, 08h30
  2. Mauvaise affectation de variable dans une boucle
    Par Isiker dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 08/10/2009, 00h42
  3. Réponses: 2
    Dernier message: 24/03/2009, 09h09
  4. [ANT] affectation de variables dans une boucle
    Par dino_xrc dans le forum ANT
    Réponses: 6
    Dernier message: 17/12/2007, 19h47
  5. [SQL] Affectation d'une variable dans une boucle
    Par monlam dans le forum PHP & Base de données
    Réponses: 9
    Dernier message: 25/10/2007, 14h41

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