Recherche d'un nombre

Discutez d'informatique ici !
Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 18:42

par Rockleader » 14 Oct 2012, 08:44

Effectivement, une condition vaut soit vrai, soit faux. c'est rassurant.



Ok, merci, je pense avoir franchi un bon cap là, en comprenant cette notion.



Ce qui me titillait au début pour en revenir à ma question, c'était d'affecter la valeur false à trouve, parce que trouve connotait plutot une valeur true...mais je comprends mieux maintenant.
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !



Avatar de l’utilisateur
fatal_error
Membre Légendaire
Messages: 6610
Enregistré le: 22 Nov 2007, 12:00

par fatal_error » 14 Oct 2012, 09:14

ben si tu comprends mieux,
EN jouant avec les négations comme tu dis, pour que la boucle s'arrête il faudrait que les deux conditions soient fausses. Or celle sur le compteur est toujours vrais.

essaies de modifier les conditions afin que tu puisses remplacer le ET par OU et conserver le bon fonctionnement de ta boucle.

Un indice, si tu listes les conditions de sortie de ta boucle, tu aurais envie de prendre le contraire pour ... ne pas en sortir
la vie est une fête :)

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 18:42

par Rockleader » 14 Oct 2012, 09:23

Ah donc il me faudrait dire tant que compteur supérieur au nombre (false sauf quand on dépassera le nombre de tentative) OU tant que trouve vaut false. Donc au final l'on s'arrêterait dès que trouve devient true, car la condition sur le compteur est false.
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
fatal_error
Membre Légendaire
Messages: 6610
Enregistré le: 22 Nov 2007, 12:00

par fatal_error » 14 Oct 2012, 09:35

t'as fait que la moitié, il te reste à prendre la négation du tout (pour que ta condition avec le OU se comporte comme ta condition avec le ET), et bien sûr à tester en codant, pour vérifier qu'on a pas dit d'énormités :)
la vie est une fête :)

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 18:42

par Rockleader » 16 Oct 2012, 17:55

Je suis content, aujourd'hui en TP, j'ai eu un exo qui nous demandait d'écrire une fonction déterminant si un nombre est premier ou non, et j'ai réussi à appliquer ce que j'avais retenu des booléen.
Le programme quand à lui renvoie true pour un nombre premier et false pour un non premier compris entre un et 100 pour l’exercice mais ça on s'en fiche.
En plus de ça je pense avoir compris comment marchent les appels de fonctions et ça aussi c'est bien.

Voilà le code:

Code: Tout sélectionner
with entrees_sorties; use entrees_sorties;
--Cherche les nombre premier entre 1 et 100
procedure deux is
  function estPremier (n:Integer) return Boolean is
    k:Integer;
    begin
      k := 2;
      While (n mod k /= 0) and (k < n) loop
   k := k+1;
      end loop;
      if (n = k) then
   return TRUE;
      else
   return FALSE;
      end if;
    end estPremier;
cpt:Integer;
begin
  cpt := 1;
  While(cpt < 100) loop
   
    if (estPremier(cpt)) then
      put(cpt);put(estPremier(cpt));
    else
      put(cpt);put(estPremier(cpt));
    end if;
    cpt := cpt + 1;
  end loop;
end deux;



J'ai quand même une question, j'ai défini ma fonction comme rendant un booléen true or false. Or quand je met if (n=k) return true, je pourrais très bien mettre return n'importe quelle chaine de caractère, par exemple return est premier, la fonction continuerait toujours à afficher un booléen sauf que sa valeur prendra est premier au lieu de true et n'est pas premier au lieu de false, c'est ça ?







ET enfin, une question un peu bête surement, mais elle me tarode l'esprit...


La fonction racine carré est censé être sqrt. Or, celle ci n'est pas dans ma bibliothèque ada. Donc, si j'ai envie de créer cette fonction de la mettre dans un package pour m'en servir à chaque fois, comment est ce que je pourrais faire ?
J'ai bien entendu pensé à la puissance 1/2...mais apparemment d'après mon prof, ça ne peut pas passer parce que 1/2 est un flottant et ça ne pourra pas calculer la puissance d'un flottant.

Je suis d'accord avec ça, mais alors comment font les programmeurs qui veulent calculer une racine carrée ou toute autre puissance flottante. du genre pi...
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Dlzlogic
Membre Transcendant
Messages: 5273
Enregistré le: 14 Avr 2009, 12:39

par Dlzlogic » 16 Oct 2012, 18:47

Rockleader a écrit:ET enfin, une question un peu bête surement, mais elle me tarode l'esprit...


La fonction racine carré est censé être sqrt. Or, celle ci n'est pas dans ma bibliothèque ada. Donc, si j'ai envie de créer cette fonction de la mettre dans un package pour m'en servir à chaque fois, comment est ce que je pourrais faire ?
J'ai bien entendu pensé à la puissance 1/2...mais apparemment d'après mon prof, ça ne peut pas passer parce que 1/2 est un flottant et ça ne pourra pas calculer la puissance d'un flottant.

Je suis d'accord avec ça, mais alors comment font les programmeurs qui veulent calculer une racine carrée ou toute autre puissance flottante. du genre pi...

Bonjour,
D'abord, un point important, à la racine d'un langage, il n'y a généralement aucune fonction. Toutes ont été écrites par des programmeurs avec ce que sait faire une machine, c'est à dire pas grand-chose.
Pour la racine carrée, je vais vous donner une indication.
Soit à calculer A = sqrt(B).
Ca s'écrit A² = B.
J'écris A = a + b; alors A² = a² + 2ab + b²
Comme j'ai pris soin de prendre b petit, je peux négliger son carré.
On calcule une valeur approchée de A et on recommence jusqu'à avoir un écart inférieur à l'écart qu'on se tolère.

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 18:42

par Rockleader » 16 Oct 2012, 19:02

Dlzlogic a écrit:Bonjour,
D'abord, un point important, à la racine d'un langage, il n'y a généralement aucune fonction. Toutes ont été écrites par des programmeurs avec ce que sait faire une machine, c'est à dire pas grand-chose.
Pour la racine carrée, je vais vous donner une indication.
Soit à calculer A = sqrt(B).
Ca s'écrit A² = B.
J'écris A = a + b; alors A² = a² + 2ab + b²
Comme j'ai pris soin de prendre b petit, je peux négliger son carré.
On calcule une valeur approchée de A et on recommence jusqu'à avoir un écart inférieur à l'écart qu'on se tolère.



Une sorte de méthode d'euler en sorte non ? A² va progressivement tendre vers la valeur a que l'on désire.


Mais en loccurence là A² ne fera qu'augmenter alors que A est plus petit que A²...
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

LeJeu
Membre Irrationnel
Messages: 1142
Enregistré le: 24 Jan 2010, 21:52

par LeJeu » 17 Oct 2012, 00:17

Rockleader a écrit:
Code: Tout sélectionner
      While (n mod k /= 0) and (k < n) loop
   k := k+1;
      end loop;


Tu peux faire mieux comme test avec : (k*k < n), ca doit économiser des tours de boucles
Code: Tout sélectionner
 cpt := 1;
  While(cpt < 100) loop
   
    if (estPremier(cpt)) then
      put(cpt);put(estPremier(cpt));
    else
      put(cpt);put(estPremier(cpt));
    end if;
    cpt := cpt + 1;
  end loop;


Il y a une petite erreur de frappe ci dessus, ilne faut pas rappeler "estPremier"
tu devais penser à
Code: Tout sélectionner
 cpt := 1;
  While(cpt < 100) loop
   
    if (estPremier(cpt)) then
      put(cpt);put("est premier");
    else
      put(cpt);put("n'est pas premier");
    end if;
    cpt := cpt + 1;
  end loop;


Rockleader a écrit:J'ai quand même une question, j'ai défini ma fonction comme rendant un booléen true or false. Or quand je met if (n=k) return true, je pourrais très bien mettre return n'importe quelle chaine de caractère, par exemple return est premier, la fonction continuerait toujours à afficher un booléen sauf que sa valeur prendra est premier au lieu de true et n'est pas premier au lieu de false, c'est ça ?

Non, tu ne peux pas faire un return de n'importe "quoi", justement car tu as déclaré ta fonction comme retournant un Booléen, donc le compilateur repérera l'erreur et rejettera ton code alors ! ( ou l’interpréteur)

Rockleader a écrit:La fonction racine carré est censé être sqrt. Or, celle ci n'est pas dans ma bibliothèque ada. Donc, si j'ai envie de créer cette fonction de la mettre dans un package pour m'en servir à chaque fois, comment est ce que je pourrais faire ?
J'ai bien entendu pensé à la puissance 1/2...mais apparemment d'après mon prof, ça ne peut pas passer parce que 1/2 est un flottant et ça ne pourra pas calculer la puissance d'un flottant.
Je suis d'accord avec ça, mais alors comment font les programmeurs qui veulent calculer une racine carrée ou toute autre puissance flottante. du genre pi...


Tu vois bien sûr que pour les puissances entières, c'est tout simple : une boucle de multiplication suffit

pour les puissances non entières et entre autres 1/2 il faut changer de techno


c'est pour ça que la régle à calcul , et les tables de log ont été inventées....

Avec l'ordi c'est plus facile..... ci dessous un paper intéressant sur comment calculer le log :

http://www.mlfmonde.fr/IMG/pdf/31_40_ams62.pdf

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 18:42

par Rockleader » 17 Oct 2012, 07:57

Il y a une petite erreur de frappe ci dessus, ilne faut pas rappeler "estPremier" tu devais penser à



Non pas vraiment car quand j’appelle la fonction dans un put, elle va m'afficher un true si le nombre est premier et un false s'il n'est pas premier. Après bien sur je pourrais mettre une chaîne de caractère mais ce n'est pas ce que je cherchais à faire ici.

Tu vois bien sûr que pour les puissances entières, c'est tout simple : une boucle de multiplication suffit pour les puissances non entières et entre autres 1/2 il faut changer de techno c'est pour ça que la régle à calcul , et les tables de log ont été inventées.... Avec l'ordi c'est plus facile..... ci dessous un paper intéressant sur comment calculer le log : http://www.mlfmonde.fr/IMG/pdf/31_40_ams62.pdf


Super merci !

Tu peux faire mieux comme test avec : (k*k < n), ca doit économiser des tours de boucles


Je suis pas convaincu de cela. Admettons k à 2 comme valeur au départ, il prendra donc les valeur de carré successives. Il sera toujours pair, il sera donc évident que k ne divisera aucun nombre impair et il se peut même qu'il ne divise pas tous les nombres pair considéré, mais ça j'y ai pas réfléchi.


Enfin bon, ce n'est que de l'optimisation, pas très important pour un exo, mais je promet d'y réfléchir quand j'aurais un peu plus de temps !
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

C.Ret
Membre Relatif
Messages: 497
Enregistré le: 02 Juil 2012, 12:33

par C.Ret » 17 Oct 2012, 08:13

Rockleader a écrit:Non pas vraiment car quand j’appelle la fonction dans un put, elle va m'afficher un true si le nombre est premier et un false s'il n'est pas premier. Après bien sur je pourrais mettre une chaîne de caractère mais ce n'est pas ce que je cherchais à faire ici.


Dans ce cas, pourquoi mettre les deux types d'affichage après un test. A chaque tour de roue, le programme appelle deux fois la fonction. Sur ton système tu ne t'en rends pas compte car c'est instantané.

Imagine que quand j'ai commencé, nous devions payer en fonction du nombre de cycle processeur que nous utilisions sur le système de notre fournisseur; ton code aurait doublé la facture ! Sans compter que s'il faut 5 min à chaque appel, il faut aussi attendre deux fois plus de temps.

Même si aujourd'hui il n'y a plus de raison pratique pour avoir à limiter les efforts réalisés par la machine, cela reste quand même une bonne pratique informatique.

Si tu veux juste afficher TRUE et FALSE pour les 100 premiers nombres, alors maintenant que tu as défini la fonction booléenne ESTPREMIER le code suivant suffit :

Code: Tout sélectionner
cpt := 1;
  While(cpt < 100) loop
    put(cpt);put(estPremier(cpt));
    cpt := cpt + 1;
  end loop;


Et là, il n'y a qu'un seul appel de la fonction par tour de manivelle.

Tu peux aussi prendre l'habitude pour les boucles dont les bornes sont prédéfinies d'utiliser la structure dédiée; c'est plus clair et évite d'avoir à incrémenter explicitement le compteur ;

Code: Tout sélectionner
FOR cpt IN Integer RANGE 1 .. 100 LOOP
     PUT(cpt);PUT(estPremier(cpt));
END LOOP;


L'ADA est un language de TYPE, une grande partie des codes utilise cet avantage en définissant des énumératin, des type particulier à chaque objet manipulé.
Une bonne habitude est de définir l'énumération (ici les 100 premiers entiers que prend cpt) en début de programme, puis dans le code d'utiliser le nom donné à ce TYPE (ou sous-TYPE).
Ainsi, si tout à cup on veux utiliser cpt allant de 1 à 1000 , il suffit simplement de changer sa déclaration dans l' "entête" du code. Et si c'est bien écrit, rien ne change dans le reste du code.

LeJeu
Membre Irrationnel
Messages: 1142
Enregistré le: 24 Jan 2010, 21:52

par LeJeu » 17 Oct 2012, 08:14

Rockleader a écrit:Non pas vraiment car quand j’appelle la fonction dans un put, elle va m'afficher un true si le nombre est premier et un false s'il n'est pas premier. Après bien sur je pourrais mettre une chaîne de caractère mais ce n'est pas ce que je cherchais à faire ici.

Non RockLeader, tu ne peux pas vouloir appeler deux fois de suite la fct sur le même nombre juste pour avoir l'affichage de "true" ou "false"
- soit tu utilises directement
put(cpt);put(estPremier(cpt));
'd'ailleurs tu vois bien que les deux lignes sont les même dans to if / else

- soit tu testes le résultat pour agir en fct
prem = estPremier(cpt)
if ( prem...)


Rockleader a écrit:Je suis pas convaincu de cela. Admettons k à 2 comme valeur au départ, il prendra donc les valeur de carré successives. Il sera toujours pair, il sera donc évident que k ne divisera aucun nombre impair et il se peut même qu'il ne divise pas tous les nombres pair considéré, mais ça j'y ai pas réfléchi.
Enfin bon, ce n'est que de l'optimisation, pas très important pour un exo, mais je promet d'y réfléchir quand j'aurais un peu plus de temps !


Je n'ai pas proposé de diviser par k*k
mais d'arreter quand k > racine(n).... c'est pas pareil

exemple si tu recherches racine(97) tu ne testes que 2 3 4 5 6 7 8 9 10
Je sais bien que tu n'es pas pressé, mais avoue que ce n'est pas cher comme optimisation
d'ailleurs à ce stade c'est presque partie intrinsèque de l'algo

D'ailleurs je mise que si tu fais le test toi même le test avec 97, à un moment tu vas dire " c'est pas la peine de continuer" avant d'avoir testées les 100 valeurs ! essaie!

LeJeu
Membre Irrationnel
Messages: 1142
Enregistré le: 24 Jan 2010, 21:52

par LeJeu » 17 Oct 2012, 08:27

C.Ret a écrit:Dans ce cas, pourquoi mettre les deux types d'affichage après un test. A chaque tour de roue, le programme appelle deux fois la fonction. Sur ton système tu ne t'en rends pas compte car c'est instantané.

Bonjour C.Ret , on s'est un peu télescopé mais on est bien d'accord tout !

C.Ret
Membre Relatif
Messages: 497
Enregistré le: 02 Juil 2012, 12:33

par C.Ret » 17 Oct 2012, 08:44

Si l'on veut optimiser le tet de primalité, on peut faire comme dans le code que j'ai donné plustôt dans ce fil, c'est à dire utiliser une liste presque uniquement compsoée de nombres premiers :

Leur formule générale est donnée par p := 6*n+s avec n=1, 2, 3 ... et s alternativemetn -1 et +1 :

On a alors une liste presque premières :
p = 5 7 11 13 17 19 23 25 27 29 31 33 ...

Code: Tout sélectionner
WITH entrees_sorties;
USE entrees_sorties;

--Cherche les nombres premiers entre 1 et 100
TYPE ListNombres IS Integer RANGE 1..100;

PROCEDURE deux IS

 FUNCTION estPremier (n:Integer) RETURN Boolean IS
   BEGIN
    k:Integer;=2;   -- Diviseur
    n:Integer:=0;   -- n et s utiles pour construire
    s:Integer:=1;   -- une liste presque uniquement première !
    p:Integer:=3;   -- prochain diviseur
    WHILE (n mod k /= 0) and (k*k  n);
 END estPremier;

 FOR cpt IN ListNombres LOOP
    PUT(cpt);
    IF estPremier(cpt)
            THEN PUTLN(" est premier") 
            ELSE  PUTLN(" est composé");
 END LOOP;

END deux;

LeJeu
Membre Irrationnel
Messages: 1142
Enregistré le: 24 Jan 2010, 21:52

par LeJeu » 17 Oct 2012, 10:15

C.Ret a écrit:On a alors une liste presque premières :
p = 5 7 11 13 17 19 23 25 27 29 31 33 ...

Disons liste réduite ...

Et donc pour notre 97, il ne reste plus que 2, 3,5 et 7 à tester , c'est notre ami Eratosthène qui va être content !

 

Retourner vers ϟ Informatique

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 6 invités

Tu pars déja ?



Fais toi aider gratuitement sur Maths-forum !

Créé un compte en 1 minute et pose ta question dans le forum ;-)
Inscription gratuite

Identification

Pas encore inscrit ?

Ou identifiez-vous :

Inscription gratuite