Générateur de nombres 1er

2»

Réponses

  • prepa75prepa75 Membre
    16:20 modifié #32
    Rebonsoir à  tous,

    pour une fois je post sans poser une question,admirez l'effort  :P

    j'ai fini mon programme et je tenais à  vous montrer mon algorythme...dites moi si il y a un problème de méthode/structure...

    merci par avance pour vos remarques

    pour information : le 78497ème nombre premier est :  999983  :D (calculé en 2mn et 39s )

    -(IBAction)decomposer:(id)sender<br />{<br />	Nbp[0] = 2;<br />	Nbp[1] = 3;<br />	<br />	nbmax = [nbadecomp intValue];<br />	<br />					if(nbmax == 0){com = @&quot;Rentrez un nombre différent de 0 !&quot;;<br />								[decompnbp setStringValue:com];}<br />	<br />					if(nbmax == 1){com = @&quot;Le nombre 1 n&#39;est ni premier ni un composé de nombres premiers...&quot;;<br />								[decompnbp setStringValue:com];<br />								nbmax = 0;}<br />	<br />if(nbmax &gt; a &amp;&amp; nbmax!=0 ) 	<br />{<br />	nbactuel = Nbp[tableaumax-1] ;<br />	<br />	if(Nbp[2] == 0){nbactuel = 3; tableauactuel = 0; tableaumax = 2;}<br />	<br />		do{<br />						<br />				do{<br />					<br />					nbdivise = nbactuel / (Nbp[tableauactuel]*1.0);<br />					if(nbdivise != floor(nbdivise))	{tableauactuel++;}<br />					else{break;}<br />			<br />					if(nbdivise != floor(nbdivise) &amp;&amp; tableauactuel &gt;= tableaumax)<br />					{<br />						Nbp[tableaumax] = nbactuel;<br />						printf(&quot;Nbp[%d] : %d&#092;n&quot;,tableauactuel,nbactuel);<br />						tableaumax++;<br />					}<br />			<br />				}while (Nbp[tableaumax] &lt;= nbactuel);<br />				<br />				tableauactuel = 0;<br />				nbactuel++;<br />		<br />			}while(nbactuel &lt; nbmax);<br />	<br />}<br />	 nbgener = tableaumax;									<br />	<br />	if(nbgenermax &lt; nbgener){nbgenermax = nbgener;}<br /><br />		k=0;l = 0;<br />	<br />		if(nbmax != 0){<br />	<br />		do{<br />			a = [nbadecomp intValue];<br />			<br />			nbdivcomp = nbmax / (Nbp[k]*1.0);<br />			<br />			if(nbdivcomp != floor(nbdivcomp))&nbsp;  {k++;}<br />			<br />			else if(nbdivcomp == floor(nbdivcomp))<br />			{<br />				decomp[l] = Nbp[k];<br />				nbmax = nbdivcomp;<br />				l++;<br />			}<br />			<br />		}while(k &lt;= sqrt(nbmax));<br />	<br />		NSString *chaine1 = [NSString stringWithFormat:@&quot;%d = %d&quot;,a,decomp[0]];<br />		<br />		for(int f = 1; f &lt; l ;f++)<br />		{<br />			NSString *chaine2 = [NSString stringWithFormat:@&quot; x %d&quot;,decomp[f]];<br />			NSString *chainetotale = [chaine1 stringByAppendingString:chaine2];<br />			<br />			chaine1 = chainetotale;<br />		}<br />	<br />	if(Nbp[k] != a) {[decompnbp setStringValue:chaine1];}<br />		<br />	if(Nbp[k] == a || decomp[0] == 0 || a == 2 || a == 3) {[decompnbp setStringValue:[NSString stringWithFormat:@&quot;%d est un nombre premier !&quot;,a]];}<br /><br />	<br />	}<br />	 <br />}
    

  • AliGatorAliGator Membre, Modérateur
    16:20 modifié #33
    J'ai pas lu en totalité ton algo ni tenté de le comprendre, mais en le parcourant en diagonale je vois déjà  que tu utilises des divisions dans une double boucle do...while, et des nombres flottants au lieu de nombre entiers (floor, etc.). C'est LE truc idéal pour ralentir à  mort ton algo.
    Une division, c'est coûteux* : c'est déjà  bien plus coûteux qu'une multiplication, et en plus les calculs flottants (avec des nombre à  virgule, quoi) sont également bien plus coûteux que les calcules en nombre entiers.
    Or dans ton cas ton problème est justement sur des nombres entiers (les nombres premiers), pourquoi donc passer par les nombres décimaux dans ton algo ? Rien que ça ralentit le tout. Et comme mentionné dans un message plus haut (par Philippe je crois), pour savoir si a est un multiple de b, avec a et b entier, il suffit de regarder si (a%b==0) : carrément moins coûteux qu'une division, et en plus tu ne travailles qu'avec des entiers (int).

    Je n'ai pas trop regardé comment fonctionne ton algo dans l'ensemble et si le reste du code est bien fait où s'il y a d'autres trucs à  améliorer, mais déjà  si tu fais rien que cette modification, de remplacer tes divisions de float et tes comparaisons avec floor** par un test sur le modulo ([tt]nbactuel % Nbp[tableauactuel][/tt]) à  mon avis tu auras un gain vraiment non négligeable, et tes 2'39 vont fondre comme neige au soleil.



    * quand je dis coûteux, c'est à  l'échelle de l'optimisation : évidemment une petite division comme ça entre deux nombres ça ne fait pas de mal, mais dans le cas d'un algo que tu cherches à  optimiser, la moindre microseconde coûte, surtout dans des boucles répété plein de fois.

    ** en plus en théorie la formule utilisant la comparaison avec floor introduit potentiellement un risque d'erreur dû à  l'erreur d'arrondi, même si FLT_EPSILON est faible il n'en n'est pas moins non nul.
  • prepa75prepa75 Membre
    16:20 modifié #34
    Ok merci Ali je ne savais pas que la division étais aussi compliquée pour lui je vais modifier ça et je reposte... :)
  • AliGatorAliGator Membre, Modérateur
    16:20 modifié #35
    :) Tu verras si tu as prochainement des cours d'algorithmie ou d'info un peu plus bas niveau dans ton école, y'a plein de trucs intéressants à  apprendre sur le sujet :D

    En même temps c'est un peu compréhensible qu'une division soit plus long (en terme de nombre de cycles processeur) qu'une multiplication, et qu'un calcul sur des flottants soit plus long qu'un calcul sur des nombres entiers (surtout quand on sait que les flottants sont codés suivant la norme IEEE.754, si ça t'intéresse de te documenter dessus pour mieux comprendre).


    Pour des usages ponctuels ou de tous les jours, ça n'a aucune incidence dans ton programme, (que le calcul prenne 1 cycle ou 4 cycles d'horloge, à  la vitesse où c'est cadencé tu ne t'en apercevra pas) mais pour des algos, les passes d'optimisation, etc. ces quelques cycles en plus multiplié par un bon paquet d'itérations, tu vois vite la différence entre un algo en O(n) et un en O(log(n)) !

    L'algorithmie et l'optimisation de ces algo est un sujet vaste et passionnant, et on voit vite que dans le contexte d'optim d'un algo, certains choix pouvant paraà®tre anodins peuvent changer beaucoup s'ils sont bien choisis, et que certains algos ou idées toutes bêtes peuvent faire gagner énormément mine de rien :)
  • prepa75prepa75 Membre
    16:20 modifié #36
    Normalement je devrais en effet avoir des cours d'algo,ainsi que l'initiation au C et C++ voire Java  :D

    ça a l'air super intéressant et c'est concret et utile donc tout benef 
  • prepa75prepa75 Membre
    16:20 modifié #37
    Voici mon nouvel algorythme; cette fois-ci calculé en 1mn et 6s

    qu'en pense-tu Ali ?
    <br /><br />-(IBAction)decomposer:(id)sender<br />{<br />	Nbp[0] = 2;<br />	Nbp[1] = 3;<br />	<br />	nbmax = [nbadecomp intValue];<br />	<br />					if(nbmax == 0){com = @&quot;Rentrez un nombre différent de 0 !&quot;;<br />								[decompnbp setStringValue:com];}<br />	<br />					if(nbmax == 1){com = @&quot;Le nombre 1 n&#39;est ni premier ni un composé de nombres premiers...&quot;;<br />								[decompnbp setStringValue:com];<br />								nbmax = 0;}<br />	<br />if(nbmax &gt; a &amp;&amp; nbmax!=0 ) 	<br />{<br />	nbactuel = Nbp[tableaumax-1] ;<br />	<br />	if(Nbp[2] == 0){nbactuel = 3; tableauactuel = 0; tableaumax = 2;}<br />	<br />		do{<br />						<br />				do{<br />					<br />					if(nbactuel % Nbp[tableauactuel] != 0)<br />					{<br />						tableauactuel++;<br />											}<br />					else if(nbactuel % Nbp[tableauactuel] == 0)<br />					{<br />						break;<br />					}<br />			<br />					if(nbactuel % Nbp[tableauactuel] != 0 &amp;&amp; tableauactuel == tableaumax&nbsp; -1)<br />					{<br />						Nbp[tableaumax] = nbactuel;<br />						printf(&quot;Nbp[%d] : %d&#092;n&quot;,tableauactuel,nbactuel);<br />						tableaumax++;<br />					}<br />			<br />				}while (Nbp[tableaumax] &lt; nbactuel);<br />				<br />				tableauactuel = 0;<br />				nbactuel++;<br />		<br />			}while(nbactuel &lt; nbmax);<br />	<br />}<br />	 nbgener = tableaumax;									<br />	<br />	if(nbgenermax &lt; nbgener){nbgenermax = nbgener;}<br /><br />		k=0;l = 0;<br />	<br />		if(nbmax != 0){<br />	<br />		do{<br />			a = [nbadecomp intValue];<br />			<br />			nbdivcomp = nbmax / (Nbp[k]*1.0);<br />			<br />			if(nbdivcomp != floor(nbdivcomp))&nbsp;  {k++;}<br />			<br />			else if(nbdivcomp == floor(nbdivcomp))<br />			{<br />				decomp[l] = Nbp[k];<br />				nbmax = nbdivcomp;<br />				l++;<br />			}<br />			<br />		}while(k &lt;= nbmax);<br />	<br />		NSString *chaine1 = [NSString stringWithFormat:@&quot;%d = %d&quot;,a,decomp[0]];<br />		<br />		for(int f = 1; f &lt; l ;f++)<br />		{<br />			NSString *chaine2 = [NSString stringWithFormat:@&quot; x %d&quot;,decomp[f]];<br />			NSString *chainetotale = [chaine1 stringByAppendingString:chaine2];<br />			<br />			chaine1 = chainetotale;<br />		}<br />	<br />	if(Nbp[k] != a) {[decompnbp setStringValue:chaine1];}<br />		<br />	if(Nbp[k] == a || decomp[0] == 0 || a == 2 || a == 3) {[decompnbp setStringValue:[NSString stringWithFormat:@&quot;%d est un nombre premier !&quot;,a]];}<br /><br />	<br />	}<br />
    

  • Philippe49Philippe49 Membre
    16:20 modifié #38
    Retire les printf( ) et les NSString formatés dans ta méthode ... tu verras l'impact sur le temps d'exécution.
    Dans ce genre de situation, on calcule une fois pour toutes les nombres premiers dont on a besoin que l'on stocke dans un tableau (pour les nombres premiers < 1 million c'est une boucle calcul de l'ordre du dixième, du centième de seconde)
  • AliGatorAliGator Membre, Modérateur
    avril 2010 modifié #39
    Encore en lecture en diagonale (donc sans chercher à  comprendre l'algo quoi), je vois :
    • encore des "if (x != floor(x))" au lieu de "if (a%b != 0)"
    • un "if (test) ... else if (!test) ..." donc inutile (le "else" tout seul au lieu de "else if" suffit, là  tu perds des cycles d'horloge à  faire un test inutile, et en plus tu fais 2x ton calcul "nbactuel%Nbp[tableauactuel]" !
    • un printf, ça prend du temps et ces cycles d'horloge aussi, mine de rien l'affichage couteux aussi. Si tu testes un algo avec des NSLog ou printf et le même algo sans les printf tu vas vite t'en apercevoir
    • Très légère optimisation (je me demande même si le compilateur ne la fait pas toute seule), préférer "++x" à  "x++" quand tu n'as pas besoin de post-increment (quand cela ne change pas ton algo de faire un pre-increment ou le post-increment) : le post-increment oblige le compilo à  mettre de côté la valeur courante le temps du calcul, bien souvent inutilement
    • en parlant d'optimisation que le compilateur fait tout seul, dans les réglages de ton projet, vérifier quel niveau d'optimisation est choisi pour la compilation (correspond au flag -O de gcc, -O0 = pas d'optim, -O1, -O2, -O3 = il fait de plus en plus d'efforts pour optimiser). Normalement d'ailleurs dans les configurations de compilation par défaut, la config "Debug" n'optimise pas ou peu le code, la config "Release" l'optimise au mieux, donc tu devrais voir une différence de vitesse entre ces deux configs.


    Voilà , encore un peu de ménage à  faire :P
    Tu verras, après tout ça déjà  tu pourras comparer le temps d'exécution du nouveau programme nettoyé (et optimisé en mode release) avec ton temps d'origine, comme quoi avec des modifications simples (même pas dans la logique décisionnelle de l'algo, en plus), on peut facilement accélérer genre x4 la vitesse de calcul...
  • AliGatorAliGator Membre, Modérateur
    16:20 modifié #40
    PS : Pour faire tes calculs de temps que prend ton algo et ton programme, théoriquement il ne suffit pas simplement de le lancer et chronométrer le temps avant qu'il te donne la réponse :
    • Il existe des commandes shell (comme "time" typiquement) qui permet de mesurer le temps d'exécution d'un programme (pour que cela ait un sens il faut bien sûr que ton programme lance le calcul tout de suite sans te demander de rentrer une valeur ou afficher une interface graphique -- car sinon le temps que tu tapes la valeur et valide pour lancer le calcul pouvant varier -- et qu'il finisse dès le calcul terminé ; sinon ça va fausser le chronométrage bien sûr). C'est donc adapté pour les programmes de type "ligne de commande", et pas aux programmes avec une interface graphique ou un prompt. Mais bon à  connaà®tre

    • Mais pour correctement évaluer le temps de calcul d'un algo, surtout, il faut :
      • L'exécuter plusieurs fois de suite, car d'une part ça permet de faire une moyenne, et en plus avec les processeurs modernes et les architectures diverses et surtout les systèmes de cache, un programme peut mettre un temps T à  faire un calcul la première fois, et mettre bien moins de temps la seconde s'il le proc a ce qu'il faut dans son cache...
      • Effectuer des relevés de temps pour plusieurs valeurs d'entrée : ici certes pour vérifier que tu optimises ton algo tu peux comparer le temps d'exécution toujours pour la même valeur d'entrée, mais si tu veux vraiment avoir une idée de la rapidité de ton algo dans son ensemble, faut regarder ses temps pour diverses valeurs d'entrée n. Pour voir s'il est plutôt linéaire O(n) ou quadratique O(n²) ou au contraire logarithmique O(log(n), car ce qui est intéressant c'est aussi de savoir s'il est de plus en plus lent plus la valeur d'entrée n est grande, et si oui à  quelle vitesse sa rapidité se dégrade, etc


    A priori je dirai (uniquement à  vue de nez) que c'est un algo en O(n.log(n)) (double boucle do...while, mais c'est pas du n² pour autant puisque pour chaque nombre n à  tester tu ne re-parcourres que le tableau des nombres premiers précédemment calculés, et pas tous les diviseurs de 0 à  n), ce qui est plutôt encourageant pour un algo de primes.
  • prepa75prepa75 Membre
    16:20 modifié #41
    dans 1271335404:

    Retire les printf( ) et les NSString formatés dans ta méthode ... tu verras l'impact sur le temps d'exécution.
    Dans ce genre de situation, on calcule une fois pour toutes les nombres premiers dont on a besoin que l'on stocke dans un tableau (pour les nombres premiers < 1 million c'est une boucle calcul de l'ordre du dixième, du centième de seconde)


    en effet ça joue un ptit peu aussi...je savais pas qu'il fallait penser à  autant de truc pour optimiser  :P

    quand tu dit de l'ordre du centième de seconde c'est pour calculer les nombres premiers < 1 million?parsque même optimisé à  fond ça peut pas aller aussi vite ! à  moins que mon algorythme soit vraiment mal foutu.en effet dans mon prog je les stocker dans un tableau,mais c'est le but du programme donc je les regénèrent à  chaque lancement.
  • Philippe49Philippe49 Membre
    16:20 modifié #42
    Pour l'instant, j'en suis là  dans mes tests :
    On détecte les nombres premiers entre 1 et Nmax, pour les nombres premiers < 1 million, j'en suis à  6 millièmes de secondes.

    <br />% pgm<br />Nmax&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  Temps écoulé&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; rapport temps/(N*sqrt(log(N))<br />10^2		 0.0020 millièmes de seconde&nbsp; &nbsp; &nbsp;  	9.3e-09 <br />10^3		 0.0040 millièmes de seconde&nbsp; &nbsp; &nbsp;  	1.5e-09 <br />10^4		 0.0580 millièmes de seconde&nbsp; &nbsp; &nbsp;  	1.9e-09 <br />10^5		 0.5360 millièmes de seconde&nbsp; &nbsp; &nbsp;  	1.6e-09 <br />10^6		 5.7770 millièmes de seconde&nbsp; &nbsp; &nbsp;  	1.6e-09 <br />10^7		 6.2622 centièmes de seconde&nbsp; &nbsp; &nbsp;  	1.6e-09 <br />10^8		 2.0788 secondes&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 	&nbsp; &nbsp; &nbsp; &nbsp; 4.8e-09 <br />10^9		26.4230 secondes&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 	&nbsp; &nbsp; &nbsp;  5.8e-09 <br />
    


  • prepa75prepa75 Membre
    16:20 modifié #43
    Waouw c'est assez impressionant ! je retire ce que j'ai dit ! je suppose que l'on a pas tout à  fait le même algorythme...  :P
  • Philippe49Philippe49 Membre
    16:20 modifié #44
    J'applique le crible d'Erathostène que tu as évoqué un peu plus haut

  • prepa75prepa75 Membre
    16:20 modifié #45
    dans 1271352300:

    J'applique le crible d'Erathostène que tu as évoqué un peu plus haut


    sérieux c'est Erathostène qui la trouvé ? je savais pas que ça avais un nom cette méthode...je dit pas que j'arrive à  son ptit orteil mais je suis content de savoir que j'ai fait pareil que lui sans le savoir 

    le truc c'est que j'utilise un interface graphique et je ne le fait pas dans le shell.Et je ne fait pas que afficher les nombres 1er,mon prog décompose aussi le nombre rentré en nombres premiers et l'affiche.

    lorsque j'enlève les printf et les NSString il va énormement plus vite ! :P
  • prepa75prepa75 Membre
    16:20 modifié #46
    Au fait Philippe tu as quoi comme mac ? je dit pas que c'est pas équitable mais si ta pas la même machine c'est de la triche...  ;) :o
  • AliGatorAliGator Membre, Modérateur
    avril 2010 modifié #47
    Impressionnant tes temps, Philippe !
    Juste pour voir, je viens de coder le crible vite fait, et "time" me donne les temps suivants pour ma part :
    nMax&nbsp;  temps<br />10^2 :&nbsp; &nbsp; &nbsp;  1ms<br />10^3 :&nbsp; &nbsp; &nbsp;  1ms<br />10^4 :&nbsp; &nbsp; &nbsp;  7ms<br />10^5 :&nbsp; &nbsp;  339ms<br />10^6 :&nbsp; 19s<br />...
    
    Du coup comment tu arrives à  des temps si bas Philippe ?

    Voilà  mon code, compilé avec [tt]gcc primes.c -O3 -o primes[/tt] et mesuré avec [tt]time ./primes 10000[/tt] par exemple
    #include &lt;stdlib.h&gt;<br />#include &lt;stdio.h&gt;<br /><br />// doit être assez large pour contenir le nombre de nombres premiers à  stocker<br />#define PRIMES_TAB_SIZE 500000<br /><br />int main(int argc, char* argv&#91;])<br />{<br />&nbsp; int primes[PRIMES_TAB_SIZE];<br />&nbsp; int nbPrimes = 0; // found primes<br />&nbsp; int testedVal, idx, nMax;<br />&nbsp; int hasDivider;<br />&nbsp; <br />&nbsp; if (argc&lt;2) {<br />&nbsp; &nbsp; printf(&quot;Usage: %s Nmax&#092;n&quot;,argv[0]);<br />&nbsp; &nbsp; exit(1);<br />&nbsp; }<br />&nbsp; nMax = atoi(argv[1]);<br /><br />&nbsp; primes[nbPrimes++] = 2;<br />&nbsp; // 2 est le premier nombre premier<br />&nbsp; // pour les suivants, on part de 3, et on incrémente de 2 en 2<br />&nbsp; // (et non de 1 en 1) comme ça on ne teste que les nombres impairs<br />&nbsp; for(testedVal=3;testedVal&lt;nMax;testedVal+=2)<br />&nbsp; {<br />&nbsp; &nbsp; hasDivider = 0;<br />&nbsp; &nbsp; for(idx=0;idx&lt;nbPrimes;++idx)<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; if (testedVal % primes[idx] == 0) // found a multiple, so testedVal is not a prime<br />&nbsp; &nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; hasDivider = 1;<br />&nbsp; &nbsp; &nbsp; &nbsp; break;<br />&nbsp; &nbsp; &nbsp; }<br />&nbsp; &nbsp; }<br />&nbsp; &nbsp; if (!hasDivider) primes[nbPrimes++] = testedVal;<br />&nbsp; }<br />&nbsp; <br />&nbsp; /*<br />&nbsp; for(idx=0;idx&lt;nbPrimes;++idx) {<br />&nbsp; &nbsp; printf(&quot;[%03d] %d&#092;n&quot;,idx,primes[idx]);<br />&nbsp; }<br />&nbsp; */<br />}
    
    Testé sur mon MacBook Pro Core2Du 2.2GHz
  • prepa75prepa75 Membre
    16:20 modifié #48
    héhé je vois que mon ptit jeu amuse tout le monde...  :P

    je suis content parsque je suis à  19s aussi pour un million mais le problème c'est que je tombe à  6'25" pour 5 millions...
    et puis mon MBP me sert de bouilloire maintenant (93° le processeur...  :( )
  • Philippe49Philippe49 Membre
    avril 2010 modifié #49
    Matos : mac book pro Intel 2,66 GHz Intel COre 2 Duo

    Le code : on enregistre le fait que le bit de position i soit le rang d'un entier i non premier (ou premier cela revient au même, mais calloc existe alors que l'initialisation à  0xFFFFFFFF prendrait du temps)
    (compilé -O3 aussi)

    Ceci dit, je n'ai pas essayé, c'est peut-être moins coûteux en temps de travailler sur les octets plutôt que sur les bits (pour la petite histoire, j'avais besoin de vérifier mes macros sur les bits pour un mini-projet d'étudiants)  et mes macros sont peut-être encore optimisables ...


    <br />// Les macros :<br /><br />/***********************************************************************<br /> * getBit(a,i) est une macro qui vaut le &quot;i-ième bit&quot; de la zone mémoire<br /> * pointée par le pointeur a. sizeof(*a) doit valoir 1.<br /> * Si i &gt;= 8, (exple i=20) le bit est pris dans l&#39;octet <br /> *		- à  l&#39;adresse a+i/8, ce qui correspond à  la valeur a[i/8] (exple a[2])<br /> *		- au bit i%8	(exple 4ème octet, sur 2^3 donc)	<br /> * La valeur de la macro est un int qui vaut 0 ou 1 <br /> ***********************************************************************/<br />#define getBit(a,i)&nbsp; (((a)[(i)/8] &amp; 1&lt;&lt;((i)%8) )!=0)			<br /><br />/***********************************************************************<br /> * setBit(a,i) est une macro qui donne la valeur 1 au &quot;i-ième bit&quot; de la zone mémoire<br /> * pointée par le pointeur a. sizeof(*a) doit valoir 1.<br /> * Si i &gt;= 8, (exple i=20) le bit est pris dans l&#39;octet <br /> *		- à  l&#39;adresse a+i/8, ce qui correspond à  la valeur a[i/8] (exple a[2])<br /> *		- au bit i%8	(exple 4ème octet, sur 2^3 donc)	<br /> ***********************************************************************/<br />#define setBit(a,i)&nbsp; ( (a)[(i)/8] = (a)[(i)/8] | 1&lt;&lt;((i)%8) )<br /><br />int main(int argc, char * argv&#91;]){<br />	unsigned long long Nmax;&nbsp; <br />	sscanf(argv[1],&quot;%llu&quot;,&amp;Nmax);<br /><br />	int p=2,m;<br />	unsigned char * nonPrime=calloc(1+Nmax/8,1);<br />	nonPrime[Nmax/8]=0x1;<br />		<br />	while(p*p&lt;=Nmax){		<br />		// Mettre le bit à  1 sur les multiples du nombre premier p<br />		for(m=p*p;m&lt;=Nmax;m+=p) setBit(nonPrime,m);<br />		// Chercher le nombre premier suivant<br />		for(p++;getBit(nonPrime,p);p++) ;<br />	}<br />		<br />	free(nonPrime);<br />	return 0;<br />}<br />
    
  • prepa75prepa75 Membre
    16:20 modifié #50
    Peut-être que je me trompe Ali mais j'ai essayer de comprendre ton code et malgré pleins de trucs que je ne comprend pas,je crois que tu incrémente de deux en deux pour remplir ton tableau primes alors qu'il serai plus rapide d'incrémenter par les nombres premiers trouvés précédement.
    <br />&nbsp; for(testedVal=3;testedVal&lt;nMax;testedVal+=2)<br />
    


    et moi j'ai dit que j'allais jusqu'a nMax/2 et non nMax (normalement il faudrait sqrt(nMax) mais c'est plus rapide de diviser par 2 )

    sous réserve de bien avoir compris ton code...  ;)


  • prepa75prepa75 Membre
    16:20 modifié #51
    dans 1271356862:

    Matos : mac book pro Intel 2,66 GHz Intel COre 2 Duo


    ouais le tiens est plus puissant (le mien fait 2,16 GHz) mais je ne pense pas que la différence soit aussi significative 

    c'est bête de perdre autant avec l'interface graphique...ça faisait des beau temps sinon 
  • AliGatorAliGator Membre, Modérateur
    16:20 modifié #52
    Ah oui j'ai oublié de n'aller que jusqu'à  âˆšnMax
    D'ailleurs au lieu d'aller jusqu'à  n/2 (d'ailleurs pour les divisions par une puissance de 2 c'est plus rapide de faire un shift, en l'occurrence n>>1 est équivalent mais plus rapide que n/2 pour un entier), donc de tester si i<nMax/2, tu peux tester non pas que i<sqrt(nMax), mais tester que [tt]i*i<nMax[/tt] (puisque sqrt est monotone)
  • prepa75prepa75 Membre
    16:20 modifié #53
    dans 1271357743:

    Ah oui j'ai oublié de n'aller que jusqu'à  âˆšnMax
    D'ailleurs au lieu d'aller jusqu'à  n/2 (d'ailleurs pour les divisions par une puissance de 2 c'est plus rapide de faire un shift, en l'occurrence n>>1 est équivalent mais plus rapide que n/2 pour un entier), donc de tester si i<nMax/2, tu peux tester non pas que i<sqrt(nMax), mais tester que [tt]i*i<nMax[/tt] (puisque sqrt est monotone)


    oui en effet ça mérite d'être testé...

    j'ai testé la différence entre i < nMax/2 et i*i < nMax et la différence n'est pas significative du moins jusqu'a un million avec mon algorythme...mais je mesure pas du tout précisément  B) faudrait que je fasse un compteur pour ça...
  • AliGatorAliGator Membre, Modérateur
    16:20 modifié #54
    Correction de mon code pour ne tester les diviseurs que jusqu'à  [tt]primes[idx]<√testedVal[/tt] (ou plutôt [tt]primes[idx]*primes[idx]<testedVal[/tt]) en remplaçant la boucle for interne ainsi :
    &nbsp; &nbsp; for(idx=0 ; primes[idx]*primes[idx]&lt;testedVal ; ++idx)
    


    Ce qui change tout côté temps :
    nMax&nbsp;  temps<br />10^5 :&nbsp;  12ms<br />10^6 :&nbsp; 176ms<br />10^7 : 3177ms
    
  • prepa75prepa75 Membre
    16:20 modifié #55
    dans 1271336429:


    • en parlant d'optimisation que le compilateur fait tout seul, dans les réglages de ton projet, vérifier quel niveau d'optimisation est choisi pour la compilation (correspond au flag -O de gcc, -O0 = pas d'optim, -O1, -O2, -O3 = il fait de plus en plus d'efforts pour optimiser). Normalement d'ailleurs dans les configurations de compilation par défaut, la config "Debug" n'optimise pas ou peu le code, la config "Release" l'optimise au mieux, donc tu devrais voir une différence de vitesse entre ces deux configs.




    je me suis mit en mode release et en effet ça à  changé  :P par contre je n'arrive pas a trouver flag -O3 , il faut faire click-droit sur le fichier de projet dans Xcode et Get Info c'est ça ?
  • prepa75prepa75 Membre
    16:20 modifié #56
    dans 1271359672:


    Ce qui change tout côté temps :
    nMax&nbsp;  temps<br />10^5 :&nbsp;  12ms<br />10^6 :&nbsp; 176ms<br />10^7 : 3177ms
    



    Waouw en effet !! mais je ne comprend pas la différence par rapport à  avant : voici ma boucle interne peut-tu me dire comment la modifier ?
    do{<br />						<br />				do{<br />					<br />					if(nbactuel % Nbp[tableauactuel] != 0)<br />					{<br />						++tableauactuel;<br />											}<br />					else {break;}<br />			<br />					if(tableauactuel == tableaumax)<br />					{<br />						Nbp[tableaumax] = nbactuel;<br />						++tableaumax;<br />					}<br />			<br />				}while (Nbp[tableaumax]*Nbp[tableaumax] &lt; nbactuel);<br />				<br />				tableauactuel = 0;<br />				++nbactuel;<br />		<br />			}while(nbactuel &lt;= nbmax);
    

  • AliGatorAliGator Membre, Modérateur
    16:20 modifié #57
    @Philippe :

    Et en effet, mon algo (qui est à  priori le même sur le principe que prepa75) n'est pas le crible d'Erathostène si je dis pas de bétise.
    Pour chaque nombre N je vérifie qu'il s'il est divisible par un des nombres premiers trouvés avant.

    Alors que toi Philippe, tu fais vraiment le crible officiel : pour chaque nombre tu barres tous les multiples de ce nombre, puis tu cherches le prochain nombre non barré (qui est donc le prochain premier) et tu continues. Jusqu'à  âˆšnMax.
    Ce qui explique la différence de perfs ;)
  • AliGatorAliGator Membre, Modérateur
    16:20 modifié #58
    dans 1271359863:

    je me suis mit en mode release et en effet ça à  changé  :P par contre je n'arrive pas a trouver flag -O3 , il faut faire click-droit sur le fichier de projet dans Xcode et Get Info c'est ça ?
    Pour le flag -O3 c'est quand tu compiles en ligne de commande directement avec gcc (ce qu'on je fait jamais quand on utilise Xcode, Xcode appelle gcc comme il faut pour nous justement).
    Le réglage dans Xcode qui correspond se trouve en effet dans les "Build Settings" du projet (Pomme-I sur le projet dans Xcode, puis aller sur l'onglet Build), il suffit de taper "optim" dans le champ de recherche pour tomber dessus : il s'agit du réglage "Optimization Level" dans le groupe de réglages "GCC 4.2 - Code Generation" (et quand tu cliques en face de ce réglage tu vois qu'il te propose en effet les options correspondant aux flags -O0, -O1, -O2, -O3, -Os)
  • prepa75prepa75 Membre
    16:20 modifié #59
    dans 1271360435:

    Pour le flag -O3 c'est quand tu compiles en ligne de commande directement avec gcc (ce qu'on je fait jamais quand on utilise Xcode, Xcode appelle gcc comme il faut pour nous justement).
    Le réglage dans Xcode qui correspond se trouve en effet dans les "Build Settings" du projet (Pomme-I sur le projet dans Xcode, puis aller sur l'onglet Build), il suffit de taper "optim" dans le champ de recherche pour tomber dessus : il s'agit du réglage "Optimization Level" dans le groupe de réglages "GCC 4.2 - Code Generation" (et quand tu cliques en face de ce réglage tu vois qu'il te propose en effet les options correspondant aux flags -O0, -O1, -O2, -O3, -Os)


    Nikel j'ai trouvé...mais je ne risque pas d'avoir vos performances  :(
  • prepa75prepa75 Membre
    avril 2010 modifié #60
    je vous met mon .m en entier,si vous pouvez me dire où est le problème et la différence par rapport à  votre code ça serai cool 

    merci par avance  ;)

    P.S. : je peut vous mettre le projet entier si ça peut vous aider.

    [EDIT] : j'ai élaguer un ptit peu mon programme et j'ai simplifier au maximum.

    .h :
    #import &lt;Cocoa/Cocoa.h&gt;<br /><br /><br />@interface decomposition : NSObject {<br />	<br />	<br />	IBOutlet NSButton *decompositionbuton;<br />	<br />	int nbactuel;<br />	int nbmax;<br />	int Nbp[10000000];<br />	int tableauactuel;<br />	int tableaumax;<br />}<br /><br />-(IBAction)decomposer:(id)sender;<br /><br />@end<br />
    


    et .m :

    <br />#import &quot;decomposition.h&quot;<br /><br /><br />@implementation decomposition<br /><br />-(IBAction)decomposer:(id)sender<br />{<br />	Nbp[0] = 2;<br />	Nbp[1] = 3;<br />	<br />	nbmax = [nbadecomp intValue];<br />	nbactuel = 3; <br />	tableaumax = 2;<br />	<br />		do{<br />						<br />				do{<br />					<br />					if(nbactuel % Nbp[tableauactuel] != 0)&nbsp; {++tableauactuel;}<br />					else {break;}<br />			<br />					if(tableauactuel == tableaumax)<br />					{<br />						Nbp[tableaumax] = nbactuel;<br />						printf(&quot;Nbp[%d] = %d&#092;n&quot;,tableaumax,nbactuel);<br />						++tableaumax;<br />					}<br />			<br />				}while (Nbp[tableaumax]*Nbp[tableaumax] &lt; nbactuel);<br />				<br />				tableauactuel = 1;<br />				nbactuel+=2;<br />		<br />			}while(nbactuel &lt; nbmax);<br />	<br /><br />}<br /><br />@end<br />
    
Connectez-vous ou Inscrivez-vous pour répondre.