Générateur de nombres 1er
prepa75
Membre
Bonjour à tous,
après une semaine de travail intensif Xcode m'a démangé :P
Comme le dit le titre,mon programme génère des nombres 1ers .le résultat sera affiché dans un NStableView ,l'utilisateur pourra choisir soit les nombre premier jusqu'a un nombre Alpha soit les Beta-ème nombres premiers.
en plus de cela il y aura une NSProgressIndicator pour afficher la progression de la génération.
Sur le papier c'est tout beau mais voici mon 1er problème :
la barre de progression s'affiche uniquement lorsque la génération est terminée ,elle passe directement de 0% à 100%.pourtant j'ai mis un printf pour verifier que la valeur varie bien
voici mon code :
après une semaine de travail intensif Xcode m'a démangé :P
Comme le dit le titre,mon programme génère des nombres 1ers .le résultat sera affiché dans un NStableView ,l'utilisateur pourra choisir soit les nombre premier jusqu'a un nombre Alpha soit les Beta-ème nombres premiers.
en plus de cela il y aura une NSProgressIndicator pour afficher la progression de la génération.
Sur le papier c'est tout beau mais voici mon 1er problème :
la barre de progression s'affiche uniquement lorsque la génération est terminée ,elle passe directement de 0% à 100%.pourtant j'ai mis un printf pour verifier que la valeur varie bien
voici mon code :
-(IBAction)Generer:(id)sender<br />{<br /> nbactuel = 1;<br /> diviseur = 3.0;<br /> compteur = 2;<br /> nbmax = 10000;<br /> printf("le 1er nombre 1er est : 2\n");<br /><br />do<br /> {<br /> nbdivisepair = nbactuel / 2.0;<br /> pourmilleprog = (1000*nbactuel)/nbmax ; //détermination de la variable "pourmille"<br /> printf("pourmillage de la barre : %f\n" , pourmilleprog);<br /> [progression setDoubleValue:pourmilleprog]; //affichage de la barre de progression<br /><br /> if(nbdivisepair == floor(nbdivisepair)) //c'est un nombre pair<br /> { <br /> nbactuel++; //on passe au nombre suivant<br /> }<br /> <br /> do{<br /> <br /> nbdivise = nbactuel / (diviseur*1.0);<br /><br /> if(nbdivise != floor(nbdivise)) //si le nombre n'est pas divisible<br /> {<br /> diviseur++; //on passe au diviseur suivant<br /> }<br /> <br /> else <br /> {<br /> break; //sinon on sort de la boucle for<br /> }<br /> <br /> if(nbdivise != floor(nbdivise) && diviseur == nbactuel - 1) //si le nombre n'est divisible que par lui-même...<br /> {<br /> printf("le %deme nombre 1er est : %d\n" ,compteur, nbactuel);<br /> compteur++;<br /> <br /> }<br /> }while (diviseur <= nbactuel - 1);<br /> <br /> nbactuel++;<br /> diviseur = 3.0; //reinitialisation du compteur<br /> <br /> }while(nbactuel < nbmax);<br />}<br /><br />@end
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Dans une application graphique, les actions effectuées sur le thread principal de l'application doivent "rendre la main" à la boucle de traitement des évènements le plus vite possible.
La solution ici est de lancer un second thread qui va effectuer les calculs. MAIS cela soulève un autre problème: Un thread secondaire n'a pas le droit d'interagir directement avec l'interface graphique. Donc pour modifier la valeur de la barre de progression, il va falloir mettre en place un mécanisme de communication entre le thread secondaire et le thread principal. Dans ce cas, la solution la plus simple, c'est la méthode "performSelectorOnMainThread", à utiliser dans le thread secondaire.
j'essaye désésperement de mettre un NSArray dans un NStableView et de l'afficher mais en vain !
donc la si tout va bien j'ai un Array contenant un object ,qui a pour valeur "nbmax"...
et je n'arive pas a trouver dans la doc la méthode qui permet de l'afficher dans le NStableView...
merci pour vos réponses
Au minimum :
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
// tu retourne [array count]
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
// tu retourne [[array objectAtIndex:indexPath] convertit en string... Fleme de chercher...]
mais je ne comprend rien du tout à ces lignes,et encore moins comment fait-on pour afficher des valeurs grâce a la datasource
une ame charitable pourrais m'expliquer l'utilité de ces 2 méthodes ?Mille merci par avance !
La réponse serait la bonne si on était dans la section iPhone, mais là , c'est une question concernant le SDK Mac . On n'a donc pas d'UITableView, mais des NSTableView.
oui en effet j'avais remarqué,j'ai compris ce que Lechatnoir voulais me faire comprendre, mais je ne comprend pas comment remplir un tableView avec un array en utilisant datasource , le livre est pas du tout explicite sur ça et je n'ai pas trouver la solution dans la doc apple
Un entier n est pair si (n%2==0)
Un entier n est divisible par m si (n%m==0)
Si les unsigned int ne te suffisent pas, tu peux toujours utiliser les long long
ULLONG_MAX= 18 446 744 073 709 551 615 = 0xFFFFFFFFFFFFFFFF
Il faut bien comprendre le principe. Lors d'un rafraichissement de la table view, c'est cette dernière qui interroge son data source. Tout ce que tu as à faire c'est de prévoir les réponses.
La table view demande à son data source le nombre d'éléments à présenter, elle appelle la méthode numberOfRowsIntableView, et on lui répond par
La table view demande ce qu'il faut afficher dans telle ligne via la méthode dédiée ci-dessous, on lui répond
Il faut naturellement que soient inscris dans monarray les valeurs à présenter.
Si tu ne remplis pas monarray avant le lancement de l'application, il est bon de mettre une instruction [maTableView reloadData] afin d'informer la table view qu'il faut qu'elle demande les infos pour se rafraà®chir.
signé : une âme charitable
Merci beaucoup pour ta réponse Philippe, j'ai compris le fonctionnement
mais lorsque je génère le tableau(marche nikel dans la console) il ne s'affiche toujours pas...j'ai bien mit le reloadData aprés le remplissage du tableau pourtant.
à quoi correspond le pointeur a, car il n'est pas utilisé...est-ce normal ? doit d'on faire quelquechose de particulier dans IB ?
voici le .m
et le .h
Merci pour ton aide.
1) A priori c'est ta fonction Generer qui crée le tableau ..
[EDIT] le devrait être extérieur à la boucle while pour ne pas recharger à chaque création ...
cela n'explique pas
2) As-tu vérifié si tes méthodes sont appelées après le reloadData ?
3) Sinon, les connections IBOutlet et datasource sont-elles opérationnelles ?
Ben si il est utilisé. La tableview demande quel objet il faut présenter, on lui renvoie l'adresse de [monarray objectAtIndex:row] .
Question judicieuse, parce que la problématique soulevée peut être élégamment résolue avec Grand Central Dispatch
Evidemment il y a le problème de la run loop, mais de toute façons le calcul des nombres premiers < 10000 ne prendra pas plus d'un dixième de seconde, alors même avec un thread on n'y verra que du feu. Il faudrait ralentir le calcul pour que le progress indicator bouge.
Quand à l'algorithme lui-même, il y a surement mieux à faire ...
1 - j'ai préféré le mettre à l'intérieur du while pour que l'affichage se fasse en temps réel , mais je suppose qu'il doit y avoir le même problème de thread et runloop comme pour la barre de progression,donc je vais le sortir
3 - mon problème venais de la, j'avais bien mis les connections la 1ere fois , mais j'ai supprimer mon tableau et en le remettant j'ai oublier le datasource...
En tout cas merci beaucoup ça marche comme je veux^^
Salut NseaProtector, j'ai le bouquin en français, et heuresement parsque même avec les explications en fr on s'y perd facilement quand tu dit pense MVC cela signifie quoi ? j'ai beau cherché la dénomination exacte je n'ai que des idées farfelues :P
pour le multi-thread en effet je l'ai feuilleté et ça me paraissais assez compliqué, mais je vais m'y mettre vu que pour une simple génération de nombres 1ers on en a besoin
sinon oui en effet je suis sur Snow Léopard.
ben oui
Voilà un code pour faire un tableau des nombres premiers : il est basé sur le fait que le plus petit diviseur premier de n est forcément déjà dans le tableau, et qu'il est inférieur ou égal à la racine carrée de n. (moins de 1 centième de seconde pour générer les 9592 nombres premiers < 100000)
en fait je vais mettre un NStextField et l'utilisateur pourra choisir jusqu'a quel nombre il souhaite aller,donc ça peut prendre plusieurs secondes.
quand à l'algorythme je suis tout à fait d'accord jme suis pas prit la tête j'ai comparé directement les nombres.
Pour des idées d'améliorations je pense à ça :
enlever les multiples ,par ex 6,9,12 etc ainsi que 10,15,etc reutiliser les nombres 1er stockés dans le tableau.
mais en règle générale,les nombres qui ne sont pas 1er ont des multiples qui sont dans les 1ers nombres donc le gain sera très minimime.
dit moi si je me trompe,parsque je dit un truc mais c'est qu'une supposition :P
waouw jsuis impressionné par ta solution,c'est tout bête et j'y avais pas pensé
je vais retourner bosser mes math....
Donc l'algorythme influence énormément le temps de calcul...logique mais j'aurai pas cru que ce soit aussi significatif sur les 10000 1ers nombres premiers
C'est une belle et rapide solution aussi, penser à utiliser le principe de la racine carrée : le premier nombre à supprimer pour le nombre premier p est p*p, car 2p, 3p, ... (p-1)p ont forcément déjà disparus quand on traite les multiples de p.
je suis content que ça te convienne en couplant les deux méthodes ont peut faire un Algo de folie bon je me calme... :P
j'ai encore 2-3 questions : concernant l'affichage instantané il faut que j'utilise le multi-thread,donc je vais m'y plonger...mais en l'utilisant peut-on aussi mettre en "Pause" le calcul,de manière à utiliser le CPU pour d'autres applications,ou bien peut-on régler l'utilisation du CPU en fonction d'une barre gérée par l'utilisateur ?Et bien évidemment si c'est à ma portée,parsque si c'est pas le cas ça attendra un ptit peu :P
2eme question : je souhaite afficher le n-ième nombre 1er dans le tableau en y ajoutant une 2eme colonne (par ex : 456ème ---> 4654) il faut que j'utilise des groupes clés et utiliser un dictionnaire comme dans le books où il y a une autre méthode ?
Mettre en pause ton thread, il n'y a sans doute aucune difficulté, sleepForTimeInterval par exemple
Pour jouer sur les priorités des process, il y a + (BOOL)setThreadPriority:(double)priority qui doit correspondre aux fonctions getpriority, setpriority du C (voir les pages man). Mais il ne faut sans doute pas penser mobiliser le processeur pour son unique application.
Si tu veux, mais ici le 456-ème va se trouver à placer avec row=456. Donc l'implémentation de
– tableView:objectValueForTableColumn:row:
peut être simplement de renvoyer [NSNumber numberWithInt:row] si row==0, et le NSNumber de monarray autrement.
concernant ma 2eme question il faut que je mette une troisième méthode? parsque le remplissage des lignes ça va mais comment le programme sait à quelle colonne il faut mettre telle objet ?
je suis désolé si je parait lourd ::) mais j'ai un peu de mal à comprendre la logique Obj-C
Tout est listé sur le Apple Developer Center, et tu as des références croisées un peu partout, en particulier sur la doc concernant classes : tu as en tout début de la doc avant le "Overview" un tableau qui indique la liste des "Companion Guides" ainsi que la liste des "Related Sample Codes", faut pas hésiter à les consulter ça donne encore plus d'infos (pratiques et techniques, les principes, et tout) que juste la doc de la classe.
Ainsi pour ton cas et tes questions posées plus haut je t'invite à consulter :
_____
*Note par exemple que la gestion d'un thread n'est pas forcément aussi simple qu'il peut y paraà®tre : faut gérer sa RunLoop (et son AutoreleasePool) un minimum, il faut bien gérer et protéger les ressources (notions de mutex, utilisation de @synchronize, ...), vérifier qu'on ne fait pas de deadlock qui gèlerait le thread (voire l'appli) ou d'inversion de priorité... Bref, ce sont des concepts pas forcément méchants, mais qu'il faut connaà®tre pour pas faire n'importe quoi et pas se lancer tête baissée dans le sujet non plus.
je vais bien lire la doc avant de m'y mettre
pour l'utilisation d'un Table View,je m'étais penché sur les liens que tu m'ai donné et je ne trouvais pas la réponse à mes questions,je n'arrive pas en fait à voir le moment où l'on dit que telle colonne correspond à tel NSArray,j'ai regardé les samples codes de "MyPhoto" ainsi que l'exemple documenté;
concrètement voici le bout de code qui me pose problème :
je n'arrive pas a le transposé à mon programme.
prepa75 : je te conseille également de lire des bouquins genre "Cocoa par la pratique" (voire sa version originale en anglais).
Bon si je te re-redirige vers encore des bouquins et de la lecture, c'est pas que je ne veuille pas te répondre, hein, mais c'est que c'est une question classique dans le genre.
En fait ici le principe est que chaque colonne est identifiée par un "identifier" (qui n'est qu'une NSString arbitraire que tu attribues à chacune de tes colonnes de ta tableview dans IB). C'est cet identifier qui va te permettre de savoir de quelle colonne il s'agit, et donc quelle valeur / quel objet retourner en conséquence dans cette méthode (en fonction de la ligne et de la colonne donc)
Ensuite, pourquoi utiliser des couples de clés ? Bah ça c'est le principe du Key-Value Coding pour simplifier ton code : Voir l'exemple justement dans cette doc
je vais essayer de me procurer ce livre.
l'exemple des children est tout à fait clair,je commence à comprendre...il me manquait cette étape là en fait :P
merci bien.
... Un coup de nostalgie ... 8--) 8--)
J'ai un petit peu de temps maintenant, mais je serais sans doute beaucoup moins investi.
@+