Inscription / Connexion Nouveau Sujet
Niveau algorithmique
Partager :

programmation

Posté par
Rana
07-04-17 à 18:37

bonsoir   , quelqu'un peut il m'aider sur cet exercice?
Un nombre parfait est égal à la somme de ses diviseurs, sauf lui-même. Exemples : 6 = 1 + 2 + 3, 28 = 1 + 2 + 4 + 7 + 14 .
chercher les entiers parfaits dans un intervalle [inf, sup] donné, afficher un message s'il n'y en a pas. Contrôler à la saisie les bornes de
//l'intervalle (inf<sup). REM. : 6 et 28 sont les deux seuls nombres parfaits de l'intervalle [1, 100].
j'ai essaye de le faire mais après execution sur les bornes [1,100] j'ai eu le message pas de nombre parfait dans cet intervalle bien qu'il ya le 6 et le 28 qui le sont.
#include<stdio.h>
void main(){
int a, b,  somme=0, i, j, k=0;  //i nombre a tester s'il est parfait
do{printf("veiller entrer les bornes d'un interval[a;b]\n a=?\n b=?\n");
scanf("%d",&a);
scanf("%d",&b);}while(b<=a);
for (i=a; i<=b; i++){
  for(j=1;j<i; j++){
if(i% j==0){somme+=j;}
                   }
                
if(somme==i) printf("%d est parfait",i);
else k=1;
                   }

if(k=1){printf("pas de nombre parfait dans un intervalle saisi");}
getch();
}
merci d'avance .

Posté par
mathafou Moderateur
re : programmation 07-04-17 à 19:13

Bonjour ,

même erreur déja rencontrée
tu dois calculer la somme des diviseurs de i
pas de tous les diviseurs de tous les nombres testés

Posté par
Rana
re : programmation 07-04-17 à 19:19

bonsoir mathafou
donc la somme ne doit pas etre dans la boucle j ?

Posté par
J-P Posteur d'énigmes
re : programmation 07-04-17 à 19:21

Voila un algo écrit sur Algobox.

VARIABLES
Nmin EST_DU_TYPE NOMBRE
Nmax EST_DU_TYPE NOMBRE
N EST_DU_TYPE NOMBRE
S EST_DU_TYPE NOMBRE
Q EST_DU_TYPE NOMBRE
i EST_DU_TYPE NOMBRE
k EST_DU_TYPE NOMBRE
flag EST_DU_TYPE NOMBRE
DEBUT_ALGORITHME
AFFICHER "Entrez Nmin >= 2"
LIRE Nmin
LIRE Nmax
flag PREND_LA_VALEUR 0
POUR k ALLANT_DE Nmin A Nmax 
	DEBUT_POUR
         N PREND_LA_VALEUR k
         S PREND_LA_VALEUR 0
         POUR i ALLANT_DE 1 A floor(sqrt(N)) 
	   DEBUT_POUR
	    Q PREND_LA_VALEUR N/i
	    SI (Q == floor(Q)) ALORS
		  DEBUT_SI
		   S PREND_LA_VALEUR S + i + Q
	    FIN_SI
	   FIN_POUR	
	   SI (S-N == N) ALORS
		DEBUT_SI
		flag PREND_LA_VALEUR 1
		AFFICHER N
		AFFICHER* " est un nombre parfait"
		FIN_SI
  FIN_POUR
  SI (flag == 0) ALORS
      DEBUT_SI
       AFFICHER* "Pas de nombre parfait dans l'intervalle demandé"
      FIN_SI
FIN_ALGORITHME


Posté par
Rana
re : programmation 07-04-17 à 19:23

mathafou @ 07-04-2017 à 19:13

Bonjour ,

même erreur déja rencontrée
tu dois calculer la somme des diviseurs de i
pas de tous les diviseurs de tous les nombres testés

ah oui je dois initialiser la somme a zero
c'est ca?

Posté par
mathafou Moderateur
re : programmation 07-04-17 à 19:32

oui tu dois initialiser somme dans la boucle "for i"
(la remettre à zéro à chaque nombre dont on veut calculer la somme des diviseurs)

Posté par
Rana
re : programmation 07-04-17 à 19:37

bonsoir J-P
j'ai un peu du mal a comprendre ce qu'il y a ecrit dans cet algo comme on a pas etudier l'algo de plus je ne comprend pas tout les variables ( S,N,Q,i...)
mais mercii!!
et encore une question  si vous pouvez m'aidez

Citation :
=Rana @ 07-04-2017 à 19:23
ah oui je dois initialiser la somme a zero

quand j'ai initialiser la somme a zero et j'ai executer le programme j'ai bieu eu que entre [1;100] il y a le 6 et le 28 qui sont des nombres parfaits mais j'ai aussi eu ce message en plus'il n'y a pas de nombre parfait . bon j'ai compris pourquoi je l'ai eu comme le else k=1 est dans la boucle mais qu'est ce que je dois changer dans mon programme pourque je n'ai plus ce message qui apparait?

Posté par
mathafou Moderateur
re : programmation 07-04-17 à 19:44

if (k = 1) est toujours true (cela met 1 dans k quelle que soit sa valeur précédente, et la valeur de cette expression toute entièr est 1 c'est à dire true)

piège classique avec les "="

Posté par
mathafou Moderateur
re : programmation 07-04-17 à 19:52

J-P : ton algorithme est défectueux
ça ne se voit pas car aucun nombre parfait n'est un carré,
mais il n'empêche que le calcul de la somme des diviseurs de N donne un résultat erroné si N est un carré parfait.

Posté par
Rana
re : programmation 07-04-17 à 19:58

Donc comment doit-on afficher le message quand il n'y a pas de nombres parfaits??

Posté par
mathafou Moderateur
re : programmation 07-04-17 à 20:03

l'erreur est archi classique. tout le monde tombe dedans régulièrement sur faute de frappe.
quand on sait où chercher on la détecte rapidement (et peut être bien qu'il y a des compilo qui sortent un warning la dessus)

ce n'est pas if (k = 1) mais if (k == 1)
(l'opérateur de comparaison et pas l'opérateur d'affectation)

Posté par
Rana
re : programmation 07-04-17 à 20:06

Oui vous avez raison je n'avais pas remarquée!!
Merci beaucoupp et bonne soirée.

Posté par
bbomaths
re : programmation 07-04-17 à 22:00

Bonsoir. Ma proposition :

#include<stdio.h>

int main()
{
int binf = 0 ;
int bsup = 0 ;
int nombre_teste = 0 ;
int somme_diviseurs = 0 ;
int nombre_diviseurs = 0 ;
int nombre_parfaits = 0 ;
int diviseur ;

printf(" Recherche des nombres parfaits dans l'intervalle [inf, sup]...\n\n") ;

printf(" > Entrez la borne inferieure de l'intervalle Binf :\n") ;

scanf("%d", &binf) ;

printf(" > Entrez la borne superieure de l'intervalle Bsup :\n") ;

scanf("%d", &bsup) ;

printf("\n") ;

// balayage des nombres entre inf et sup
for (nombre_teste = binf ; nombre_teste <= bsup ; nombre_teste++)
{
printf(" > Nombre en test : % 6d \t Diviseur(s) : ", nombre_teste) ;

somme_diviseurs = 0 ;
nombre_diviseurs = 0 ;

// recherche des diviseurs
for (diviseur = 1 ; diviseur < nombre_teste ; diviseur++)
{
if (diviseur == 1)
{
somme_diviseurs += 1 ;
nombre_diviseurs += 1 ;

printf("%d ", diviseur) ;
}
// diviseur de nombre ?
else if (nombre_teste % diviseur == 0)
{
somme_diviseurs += diviseur ;
nombre_diviseurs += 1 ;

printf("%d ", diviseur) ;
}
}

if ((nombre_teste == somme_diviseurs) && (nombre_diviseurs > 0))
{
printf("\t Nombre %d est parfait", nombre_teste) ;

nombre_parfaits += 1 ;
}

printf("\n") ;
}

if (nombre_parfaits == 0)
{
printf("\n Pas de nombre parfait dans l'intervalle saisi") ;

}
return(0) ;
}

Posté par
mathafou Moderateur
re : programmation 07-04-17 à 22:23

il y a des trucs trop compliqués là dedans n%1 = 0 quel que soit n entier (en d'autres termes 1 divise bien n quel que soit n, le reste de la division entière de n par 1 est 0)
il n'y a aucune raison de faire un cas particulier de diviseur == 1 ou pas

de plus la consigne :
"Contrôler à la saisie les bornes de l'intervalle (inf(c'est la boucle do{ ...}while(b<=a); du programme de Rana)

le programme est "verbeux" puisqu'il donne une (longue) liste de tous les nombres entiers de min à max parfaits ou pas, avec la liste exhaustive de leurs diviseurs et avec par ci par là un message supplémentaire "ce nombre [redite] est parfait"

bref la sortie est assez inutilisable si on demande de trouver les nombres parfaits entre 1 et 10000 par exemple,
genre chercher l'aiguille dans la botte de listing.

Posté par
bbomaths
re : programmation 08-04-17 à 05:15

Bonjour.

Version plus orthodoxe :

#include<stdio.h>

int main()
{
int binf = 0 ;
int bsup = 0 ;
int nombre_teste = 0 ;
int somme_diviseurs = 0 ;
int nombre_parfaits = 0 ;
int diviseur ;

printf(" Recherche des nombres parfaits dans l'intervalle [Binf, Bsup]...\n\n") ;

do
{
printf(" > Entrez la borne inferieure de l'intervalle Binf :\n") ;

scanf("%d", &binf) ;

printf(" > Entrez la borne superieure de l'intervalle Bsup :\n") ;

scanf("%d", &bsup) ;

} while (bsup <= binf) ;

printf("\n Liste des nombres parfaits :\n\n") ;

// balayage des nombres entre Binf et Bsup
for (nombre_teste = binf ; nombre_teste <= bsup ; nombre_teste++)
{
somme_diviseurs = 0 ;

// recherche des diviseurs de nombre_teste
for (diviseur = 1 ; diviseur < nombre_teste ; diviseur++)
{
// diviseur ?
if (nombre_teste % diviseur == 0)
{
somme_diviseurs += diviseur ;
}
}

// nombre_teste parfait ?
if (nombre_teste == somme_diviseurs)
{
nombre_parfaits += 1 ;

printf("\t%d\n", nombre_teste) ;
}
}

if (nombre_parfaits == 0)
{
printf("\n Pas de nombre parfait dans l'intervalle saisi") ;
}

return(0) ;
}

Posté par
Rana
re : programmation 08-04-17 à 08:49

Merciii  bbomaths

Posté par
J-P Posteur d'énigmes
re : programmation 08-04-17 à 09:10

Citation :
J-P : ton algorithme est défectueux


Non.

Rien n'empêche dans un algo de tenir compte de propriétés connues.

Il a été démontré que si un nombre est parfait, il est obligatoirement de la forme : 2^n * (2^n - 1)/2

Soit donc la moyenne arithmétique de 2 entiers consécutifs ... donc aucun nombre parfait n'est un carré.

J'infirme la remarque de mathafou ... Mon algorithme est parfaitement fonctionnel.

Posté par
mathafou Moderateur
re : programmation 08-04-17 à 09:49

Mon "défectueux" était très exagéré.
juste que dans sa boucle interne il ne calcule pas la somme des diviseurs de n
mais "autre chose" qui est "parfois" (la plupart du temps il est vrai) la somme des diviseurs, en particulier si le nombre est parfait.

prouver la justesse de cet algorithme est donc plus difficile (nécessite à priori des connaissances sur les propriétés théoriques des nombres parfaits au lieu de les chercher par force brute)

il a été démontré ?
ah bon je ne dois pas être au fait des dernières avancées en ce domaine.

il a été démontré que si un nombre pair est parfait il est de la forme ...
(et d'ailleurs réciproquement que si un nombre est de cette forme avec (2^n - 1) premier, nombre premier de Mersenne, alors il est parfait)

à ma connaissance on n'a pas prouvé l'inexistence de nombres parfaits impairs, même si on n'en a jamais trouvé.

tant qu'à faire au lieu de tester les nombres un par un et de calculer la somme des diviseurs, tu pouvais te contenter de ces seuls nombre là

Posté par
J-P Posteur d'énigmes
re : programmation 08-04-17 à 11:17

Si on veut boucher le trou très probablement  inexistant ...

VARIABLES
Nmin EST_DU_TYPE NOMBRE
Nmax EST_DU_TYPE NOMBRE
N EST_DU_TYPE NOMBRE
S EST_DU_TYPE NOMBRE
Q EST_DU_TYPE NOMBRE
i EST_DU_TYPE NOMBRE
k EST_DU_TYPE NOMBRE
flag EST_DU_TYPE NOMBRE
DEBUT_ALGORITHME
AFFICHER "Entrez Nmin >= 2"
LIRE Nmin
LIRE Nmax
flag PREND_LA_VALEUR 0
POUR k ALLANT_DE Nmin A Nmax 
	DEBUT_POUR
         N PREND_LA_VALEUR k
         S PREND_LA_VALEUR 0
         POUR i ALLANT_DE 1 A floor(sqrt(N)) 
	   DEBUT_POUR
	    Q PREND_LA_VALEUR N/i
	    SI (Q == floor(Q)) ALORS
		  DEBUT_SI
		   S PREND_LA_VALEUR S + i + Q
		   SI (Q == i) ALORS
		    DEBUT_SI
		     S PREND_LA_VALEUR S - i
		    FIN_SI
	        FIN_SI
	   FIN_POUR	
	   SI (S-N == N) ALORS
		DEBUT_SI
		flag PREND_LA_VALEUR 1
		AFFICHER N
		AFFICHER* " est un nombre parfait"
		FIN_SI
  FIN_POUR
  SI (flag == 0) ALORS
      DEBUT_SI
       AFFICHER* "Pas de nombre parfait dans l'intervalle demandé"
      FIN_SI
FIN_ALGORITHME


Posté par
mathafou Moderateur
re : programmation 08-04-17 à 11:28

oui, là ça calcule la somme des diviseurs dans tous les cas. plus rien à redire.
et du coup on n'a pas besoin de faire intervenir la théorie sur les nombres parfaits pour prouver la justesse de l'algorithme.



Vous devez être membre accéder à ce service...

Pas encore inscrit ?

1 compte par personne, multi-compte interdit !

Ou identifiez-vous :


Rester sur la page

Désolé, votre version d'Internet Explorer est plus que périmée ! Merci de le mettre à jour ou de télécharger Firefox ou Google Chrome pour utiliser le site. Votre ordinateur vous remerciera !