Erreurs dans une operation (language C)

Fermé
mireille - Modifié par mireille le 15/07/2011 à 00:59
 Antoine - 15 juil. 2011 à 21:11
Bonjour,

après avoir galérer tout la journée pour essayer de comprendre par moi meme je dois m'avouer vaincue... et completement mystifiée

voila mon probleme :

j'ai un tableau[] de 2 000 000 de cases dans lequel certaines cases sont vides et d'autres
contienne des nombres premiers. Mon but final est de trouver la somme de tout ces nombres premiers.Mais voila ... Au debut pour les 17 000 premieres cases tout ce passe bien mais a un certain moment pour mon operation :

b = b + tableau[i];

le resultat b n'est plus exact !!!
voila le code source de mon programme(j'ai marquer l'endroit ou il y a probleme)
#include <stdlib.h>
#include <stdio.h>

main()
{
float tableau[2000000] = {0};
float N = 2;
int   i = 0;
float b = 0;

for(i=0;i<=1999999;i++)
{
	tableau[i] = i;
}

while(N <= 1999999)
{
	i = N;
	
	if(tableau[i]!=0)
	{	
		while(i+N <=1999999)
		{
			i=i+N;
			tableau[i] = 0 ;
		}
	}
	N ++;
}

for(i=0;i<=1999999;i++)          <---------------------------- le probleme est ici
{
	if(tableau[i] != 0)
	{
	printf("b = %f,tableau[%d] = %f\n",b,i,tableau[i]);
	b = b + tableau[i];
	}
}                                                

printf("%f === sum\n",b);
exit(0);
}



et voila ce que ca donne :

ici on considere avec pas trop d'étonnement que tout est normal:

b = 14601053.000000,tableau[16417] = 16417.000000
 Vrai puisque  : 14601053 +  14601053 = 14617470 
  
 b = 14617470.000000,tableau[16421] = 16421.000000 
 Vrai puisque : 14617470 + 16421 = 14633891 

b = 14633891.000000,tableau[16427] = 16427.000000 

mais remarquer ici : ----------> 

b = 18245300.000000,tableau[18433] = 18433.000000 
 Faux car 18245300 + 18433 != 18263732 (la somme exacte est 18263733) 

b = 18263732.000000,tableau[18439] = 18439.000000 
Faux aussi car 18263732 + 18439 != 18282172 (mais plutot 18282171) 

b = 18282172.000000,tableau[18443] = 18443.000000 



vous voyez mon embettement ...
les resultats ne sont plus correct ...
pourtant le programme est toujours dans la meme boucle (celle que jài montrer)
serieusement je n? comprend rien mais absolument rien

et si quelqu'un pouvait m'aider je lui serais vraiment tres reconnaisscente
car je sens que mon petit coté obsessive compulsive va m'empecher de passer a autre chose tant que je n'aurrai pas resolu ce mystere

en vous remerciant d'avance :)
Mireille

p.s. jsuis pas trop habituée de poster sur des forums et j'espere sincerement avoir été assé
précise dans la description de mon probleme:)

3 réponses

Hxyp Messages postés 401 Date d'inscription vendredi 28 janvier 2011 Statut Membre Dernière intervention 27 avril 2014 54
Modifié par Hxyp le 15/07/2011 à 02:53
Bonjour,
le poblème de segmentation c'est à cause de l'allocation mémoire quand vous utilisez le type double le tableau devient trop grand alors il faut réserver la mémoire dynamiquement. Mais les double ne sont pas utiles ici vu qu'il n'y a aucune division vous pouvez utiliser des unsigned int
Pour la somme c'est bien la somme de tout les nombres premiers dans le tableau ?
En reprenant vôtre code d'une différente façon et aider de http://fr.wikipedia.org/wiki/Crible_d'Ératosthène :
#include <stdlib.h> 
#include <stdio.h> 

int main(void) 
{ 
 unsigned int *tableau; 
 unsigned int N = 2, m=2000000; 
 unsigned int i,j; 
 unsigned int b = 0; 
  
 tableau=calloc(m,sizeof(unsigned int)); 
 printf("remplissage du tableau\n"); 
 for(i=0;i<m;i++) 
 { 
  tableau[i] = i; 
 } 
 printf("tableau ok\ncheck...\n"); 

 for(i=N;i<m;i++) 
 { 
  if(tableau[i]!=0){ 
   for(j=i+i;j<m;j+=i) 
   { 
    tableau[j]=0; 
   } 
  } 
 } 
 printf("check ok\n"); 

 for(i=N;i<m;i++) 
 { 
  if(tableau[i] != 0) 
  { 
   if(i==18439) 
    printf("b = %d,tableau[%d] = %d\n",b,i,tableau[i]); 
   b = b + tableau[i]; 
  } 
 }                                                 

 printf("%d === sum\n",b); 
  
 free(tableau); 
 return 0; 
}


Ça me donne :
b = 18263738,tableau[18439] = 18439
1179908154 === sum

Est-ce correct ?
1
Je n'aurais pas mieux expliqué. C'est vrai qu'il n'est pas recommandé d'allouer des grand volume de mémoire sur la pile. Cela ralentit l'exécution et la compilation peut être très lente!
0
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015
Modifié par KX le 15/07/2011 à 11:14
float n'est pas un type de données exactes. Il est limité en précision.
Tu pourrais utiliser double qui est plus précis, mais il est quand même limité en précision.

Un peu de documentation : IEEE 754
La confiance n'exclut pas le contrôle
0
ouais c'est ce que je me suis dit mais si je change tous mes float pour des double

ca compile puis quand je lance le programme j'obtien un joli : segmentation fault instantanné
0
mais je dois avouer que j'ai pas vraiment compris pourquoi mon programme plantais automatiquement avec le message segmentation fault ... :S
une idée peut-etre ?
0
nicocorico Messages postés 799 Date d'inscription dimanche 19 juin 2011 Statut Membre Dernière intervention 3 juillet 2018 138
Modifié par nicocorico le 15/07/2011 à 07:45
Il faudrait peut-être remplacer les entiers du tableau par des booléens ^^, plutôt que de récupérer soit la valeur identique à l'index soit 0 :
for(i=0;i<m;i++)     
 {     
  tableau[i] = i;     
 } 

Mais bon ça doit fonctionner quand même...
-1