Fonction pow [Résolu]

Messages postés
8
Date d'inscription
mercredi 19 février 2014
Dernière intervention
19 février 2014
-
Bonjour,
je cherche à décomposer un entier dans un tableau.
J'ai pensé à utiliser la fonction pow, en enlevant à chaque fois k*pow(10,j), et j'ai une différence sur les unités, qui décrémentent inexplicablement. Je joins une partie du code, pour que vous me disiez si vous voyez le soucis, ou si vous avez une meilleure idée, sachant que je débute en C++, et que ce sujet est le premier devoir (CNED).
Merci d'avance pour le temps et l'aide apportés,


  //décomposition du nombre dans le tableau
while(nb!=0){
    for (j=8;j>=1;j--){
        k=0;
        while(nb-k*pow(10,j)>=pow(10,j)-0)
        {
            k++;
        }
        tab[j]=k;
        nb=nb-(k*pow(10,j));
    }
}
tab[0]=nb;
Afficher la suite 

Votre réponse

16 réponses

Meilleure réponse
Messages postés
14272
Date d'inscription
lundi 11 juillet 2005
Statut
Modérateur
Dernière intervention
7 décembre 2018
1
Merci
Hello,

C'est bien, tu gardes ton sens de l'humour ;)
Bon, ça m'a l'air complexe ton truc... Naïvement, je le ferais avec des divisions par 10 et des modulo 10:
- le modulo te permet de récupérer le chiffre des unités
- la division te permet de "déplacer" tes chiffres vers la droite

Comprends-tu ce que je veux dire?

Merci BunoCS 1

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources a aidé 98 internautes ce mois-ci

Commenter la réponse de BunoCS
Messages postés
3830
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
19 novembre 2018
1
Merci
Bonjour.

Tout d'abord, si tu débutes en C++, un petit conseil sur une erreur très classique: Évite les using namespace, voir: http://0217021.free.fr/portfolio/axel.berardino/articles/bon-usage-using-namespace

Pour ton problème, tu n'as pas besoin de tableau, ni de puissance. Je pense que tu es parti "très loin", et que tu as fortement complexifié un problème très simple. Ce n'est pas grave, ça arrive. En revanche, si ça fait vraiment 15 jours que tu dessus, c'est dommage de ne pas être venu plus tôt. Parfois, on reste bloqué sur une solution, et un oeil externe peut aider à débloquer rapidement la situation. Pour les prochaines fois, n'hésite pas à venir si tu vois que tu dépasses les 24h sur un problème donné, on t'aidera avec grand plaisir.

Ce qu'on te demande au final, si on reformule un peu, c'est d'afficher les chiffres de la droite vers la gauche, tout en les numérotant.
Si tu affiches déjà les chiffres de la droite vers la gauche, tu verras que tu auras fait 80% du problème.

Pour afficher le dernier chiffre d'un nombre on utilise nb % 10. Exemple: 123456 % 10 => 6.
Pour supprimer le dernier chiffre d'un nombre, on utilise nb / 10. Exemple: 123456 / 10 => 12345.

Avec une boucle bien placée, je pense que tu peux aisément afficher les chiffres d'un nombre de la droite vers la gauche. Puis tu ajoutes un compteur à tout ça, et tu auras ton "poid".

__________________________________________________________________________________________________
Améliorez votre expérience CodeS-SourceS avec ce plugin:
http://codes-sources.commentcamarche.net/forum/affich-10000111-plugin-better-cs-2#cptpingu-signature

Merci cptpingu 1

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources a aidé 98 internautes ce mois-ci

Commenter la réponse de cptpingu
Messages postés
3830
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
19 novembre 2018
1
Merci
Je te propose 3 solutions alternatives, de la plus simple à la plus compliquée. (Tu n'as pas vraiment besoin de pow).

La première solution, considère que l'on ne met qu'un poids sur chaque chiffre, naïvement:
#include <iostream>

int main()
{
  bool stop = false;

  while (!stop)
  {
    unsigned long int nb;
    std::cout << "Entrez un nombre, 0 pour quitter" << std::endl;
    std::cin >> nb;
    if (nb == 0)
      stop = true;
    else
    {
      unsigned int i = 0;
      while (nb != 0)
      {
         std::cout << (nb % 10) << " " << i << std::endl;
        ++i;
         nb /= 10;
      }
    }
  }

  return 0;
}



La deuxième solution, respect la consigne (affichage de chacun des poids par chiffres). On utilise un tableau fixe contenant un tableau à taille dynamique automatique (std::vector<unsigned int>).
#include <iostream>
#include <vector>

int main()
{
  bool stop = false;

  while (!stop)
  {
    std::vector<unsigned int> tab[10];
    unsigned long int nb;
    std::cout << "Entrez un nombre, 0 pour quitter" << std::endl;
    std::cin >> nb;
    if (nb == 0)
      stop = true;
    else
    {
      unsigned int i = 0;
      while (nb != 0)
      {
         tab[nb % 10].push_back(i);
         ++i;
          nb /= 10;
      }

      for (unsigned int k = 0; k < 10; ++k)
      {
         if (!tab[k].empty())
        {
           std::cout << k;
           for (unsigned int j = 0; j < tab[k].size(); ++j)
             std::cout << " " << tab[k][j];
           std::cout << std::endl;
        }
      }
    }
  }

  return 0;
}


Enfin, le troisième exemple est une solution plus généraliste. Elle fonctionne avec n'importe quelle chiffre, ou même nombre. Elle montre l'usage que l'on peut faire d'une table de "hash" (via std::map). On a une std::map qui associe un std::vector à un chiffre. C'est la solution la plus élégante, et la plus pure "C++" (pas d'introduction de C).
#include <iostream>
#include <vector>
#include <map>

int main()
{
  typedef std::map<unsigned int, std::vector<unsigned int> > map_type;
  typedef map_type::const_iterator iter;

  bool stop = false;

  while (!stop)
  {
    map_type map;
    unsigned long int nb;
    std::cout << "Entrez un nombre, 0 pour quitter" << std::endl;
    std::cin >> nb;
    if (nb == 0)
      stop = true;
    else
    {
      unsigned int i = 0;
      while (nb != 0)
      {
         map[nb % 10].push_back(i);
        ++i;
         nb /= 10;
      }

      for (iter it = map.begin(); it != map.end(); ++it)
      {
         std::cout << it->first;
         for (std::vector<unsigned int>::const_iterator jt = it->second.begin(); jt < it->second.end(); ++jt)
           std::cout << " " << *jt;
         std::cout << std::endl;
      }
    }
  }

  return 0;
}


__________________________________________________________________________________________________
Améliorez votre expérience CodeS-SourceS avec ce plugin:
http://codes-sources.commentcamarche.net/forum/affich-10000111-plugin-better-cs-2#cptpingu-signature

Merci cptpingu 1

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources a aidé 98 internautes ce mois-ci

Commenter la réponse de cptpingu
Messages postés
14272
Date d'inscription
lundi 11 juillet 2005
Statut
Modérateur
Dernière intervention
7 décembre 2018
0
Merci
Hello,
J'ai édité ton message pour rajouter les balises code. Plus d'infos ici. Merci d'y penser la prochaine fois ;)

Tu cherches à faire quoi exactement? C'est quoi nb, k, tab?

@+
Buno, Modo CS-CCM
L'urgent est fait, l'impossible est en cours. Pour les miracles, prévoir un délai...
The urgent is done, the impossible is underway. For miracles, envisage a time ...
Commenter la réponse de BunoCS
Messages postés
8
Date d'inscription
mercredi 19 février 2014
Dernière intervention
19 février 2014
0
Merci
Bonjour Bruno et merci de ton aide, j'ai fait un copier-merder, euh... coller pardon, je ferais attention la prochaine fois aux balises.
nb est un unsigned long int, limité par l'énnoncé à cette taille, et les autres variables sont des int.
Le but de l'exo est d'afficher le poids de chaque chiffre d'un nombre:
exemple, pour 234456, 6 a pour poids 0, 5 a un poids de 1, 4 a un poids de 2 et 3, 3 a un poids de 4 et 2 un poids de 5. (en parlant de poids, j'espère ne pas être trop lourd :)).
Voilà pourquoi je voulais "ranger " chaque chiffre du nombre entier dans un tableau, pour utiliser et analyser plus facilement ensuite.
J'y suis depuis 15 jours et sur la décomposition, en suivant pas à pas, j'ai parfois une erreur de 1 sur le calcul de nb-k*pow(10,j), et mathématiquement cela ne me parait pas logique.
J'ai vu sur les topics de pow une histiore de "float", mais là, c'est moi qui coule...
merci encore,
Laurent
Commenter la réponse de dubs2a
Messages postés
8
Date d'inscription
mercredi 19 février 2014
Dernière intervention
19 février 2014
0
Merci
je met l'ensemble si certains veulent bien critiquer, car ce sont mes toutes premières lignes de code, et j'ai bien conscience qu'il doit y avoir moyen d'optimiser...
En plus, je m'entraine pour mettre les balises :)

//programme affichage poids des chiffres dans un nombre
#include <iostream>
#include <math.h>

using namespace std;

int main()
{
//déclarations et initialisations
unsigned long int nb,nbr;
int tab[9],i,j,k,u,m,r;

//saisie du nombre initial, sortie pour 0
cout <<"entrez un nombre, 0 pour quitter"<<endl;
cin>>nb;
//décomposition du nombre dans le tableau
while(nb!=0){
for (j=8;j>=1;j--){
k=0;
while(nb-k*pow(10,j)>=pow(10,j)-0)
{k++;
}
tab[j]=k;
nb=nb-(k*pow(10,j));
}
}
tab[0]=nb;
//valeurs du tableau non utilisées égales à 10
r=8;
while(tab[r]==0)
{tab[r]+=10;
r--;
}

//affichage du poids de chaque chiffre
for (i=0;i<=8;i++){
if (tab[i]<10){
cout<<tab[i]<<" "<<i<<" ";
for (u=i+1;u<=8;u++){
if (tab[i]==tab[u]){
cout<<u<<" ";
tab[u]+=10;}
}
cout<<endl;
}
}
//reconstitution du nombre
nbr=0;
for (m=0;m<=8;m++){
if (tab[m]>=10){
tab[m]-=10;
}
nbr+=tab[m]*pow(10,m);
}
nbr+=1;
cout<<nbr<<endl;
cout<<"entrez un nombre, 0 pour arrêter: ";
cin>>nb;
}
return 0;
}
Commenter la réponse de dubs2a
Messages postés
8
Date d'inscription
mercredi 19 février 2014
Dernière intervention
19 février 2014
0
Merci
Je crois que je comprends, avec les divisions par 10 et modulo, je décompose dans l'autre sens, en partant des unités, non?
Cela devrait en plus simplifier la deuxième partie.
Je tente et je reposte, merci en tous cas pour la piste :)
Commenter la réponse de dubs2a
Messages postés
8
Date d'inscription
mercredi 19 février 2014
Dernière intervention
19 février 2014
0
Merci
La division par 10 et l'affectation du reste dans le tableau marche nikel, et ça évite une boucle, merci beaucoup, moi aussi quand je serais grand, je saurais coder :)

Laurent, 43 ans, 1m65, mais motivé comme un jeune!
Commenter la réponse de dubs2a
Messages postés
3830
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
19 novembre 2018
0
Merci
N'hésite pas à poster ta solution ici, afin que l'on puisse l'améliorer, ou te conseiller des solutions alternatives.

__________________________________________________________________________________________________
Améliorez votre expérience CodeS-SourceS avec ce plugin:
http://codes-sources.commentcamarche.net/forum/affich-10000111-plugin-better-cs-2#cptpingu-signature
Commenter la réponse de cptpingu
Messages postés
8
Date d'inscription
mercredi 19 février 2014
Dernière intervention
19 février 2014
0
Merci
//programme affichage poids des chiffres dans un nombre
#include <iostream>
#include <math.h>

using namespace std;

int main()
{
//déclarations et initialisations
unsigned long int nb,nbr;
int tab[9],i,j,k,l,m;

//saisie du nombre initial, sortie pour 0
cout <<"entrez un nombre, 0 pour quitter"<<endl;
cin>>nb;
//décomposition du nombre dans le tableau
while(nb!=0){
for (j=0;j<=8;j++)
{tab[j]=nb%10;
nb/=10;
}
//valeurs du tableau non utilisées égales à 10
l=8;
while(tab[l]==0)
{tab[l]+=10;
l--;
}

//affichage du poids de chaque chiffre
for (i=0;i<=8;i++){
if (tab[i]<10){
cout<<tab[i]<<" "<<i<<" ";
for (k=i+1;k<=8;k++){
if (tab[i]==tab[k]){
cout<<k<<" ";
tab[k]+=10; }//permet de ne pas réutiliser ce chiffre
}
cout<<endl;}
}
//reconstitution du nombre
nbr=0;
//réinitialisation du tableau aux valeurs d'origine
for (m=0;m<=8;m++){
if (tab[m]>=10){
tab[m]-=10;
}
nbr+=tab[m]*pow(10,m);
}
cout<<nbr<<endl;
cout<<"entrez un nombre, 0 pour arrêter: ";
cin>>nb;
}
return 0;
}



voilà, ma prose complète, si il ya des suggestions et critiques, je prends,
merci,
Laurent
Commenter la réponse de dubs2a
Messages postés
8
Date d'inscription
mercredi 19 février 2014
Dernière intervention
19 février 2014
0
Merci
Merci cptpingu,
il y avait une partie de l'énnoncé que je n'ai pas donné, c'est le format de l'affichage, qui devait être:
pour le nombre 34546 par exemple:
6 0
4 1 3
5 2
3 4
34546

(avec reconstitution du nombre à la fin)
Là, je crois que j'ai tout dit.
Cela fait vraiment plaisir de voir la solidarité que l'on trouve sur ce forum, et je n'hésiterai pas à reposter. Ceci dit, je trouve que se "creuser les méninges" m'aide à progresser. Ce qui est sur, c'est que 15 jours, c'était trop long, et j'appellerai à l'aide plus tôt.

A trés bientôt donc (la lucidité de mon grand âge :))
Laurent
Commenter la réponse de dubs2a
Messages postés
8
Date d'inscription
mercredi 19 février 2014
Dernière intervention
19 février 2014
0
Merci
Merci bcp, cptpingu,
je vais décortiquer les trois solutions, la deuxième étant d'aprés moi la plus en phase avec l'état d'avancement de mon cours, et la troisième représentant un pas supplémentaire pour moi. La première me montre qu'un problème peut être plus simple qu'il ne parait, et qu'il ne faut pas scléroser sur une "manière".
Mon but est bien sur de progresser, et ces posts m'auront bien aidé.
J'espère juste qu'un jour je pourrais aider un débutant C++, avant d'avoir besoin d'un déambulateur...
Je le dis beaucoup, mais je le pense: MERCI.
Commenter la réponse de dubs2a
Messages postés
1137
Date d'inscription
lundi 17 novembre 2003
Dernière intervention
23 janvier 2016
0
Merci
Salut,

L'affichage du résultat formaté est plus compliqué que le calcul des valeurs !
On a tendance a faire 4, 5 ou même 6 boucles dont certaines imbriquées !

Une autre solution plus orienté C que C++ en utilisant la valeur ascii des caractères et pas le calcul /10 et %10

On est pas dans l'"élégance" mais le résultat est là.
Si le prof. note le résultat, pas de problème, si il note une "manière orthodoxe" de faire, alors c'est pas bon.

void main()
{
	/*
		Exemple, si saisie 1234445555 affiche
		5	0	1	2	3
		4	4	5	6
		3	7
		2	8
		1	9
	*/
	const int MAXSIZENUM = (int)log10((double)INT_MAX)+1;/*<limit.h> largeur max pour 1 int*/
	char* buf = new char[MAXSIZENUM]; /*le nombre saisi*/
	int sizeStr; /*la taille du nombre*/

	while(true)
	{
		printf("le nombre (0 pour quitter ): ");
		scanf("%s", buf);
		sizeStr = strlen(buf);
		if(!strcmp(buf,"0")) break;

		buf = strrev(buf); /* Reverse string */
	
		int* pVals= new int[sizeStr]; /* Les chiffres */
		int* pPoids = new int[MAXSIZENUM];	/* Les poids */
		memset(pPoids, -1, sizeof(int)*MAXSIZENUM); 

		int savInd = -1, rechVal = -1; /* pseudo curseur dans la boucle */
		for(int i=0; i<sizeStr; i++)
		{
			pVals[i] = (int)buf[i]-48; /*Le chiffre en cours*/
			if(rechVal == -1 && pPoids[ pVals[i] ] == -1) /*pas encore de poids*/
			{
				pPoids[ pVals[i] ] = i;
				rechVal = pVals[i] ; 
				printf("\r\n%d \t%d", pVals[i], pPoids[ pVals[i] ]);
			}
			else
			{
				if( rechVal == -1 && savInd==-1 )
					savInd = i;
				else if( pVals[i] == rechVal) /* même poids, même ligne */
					printf("\t%d", i);
			}
			if(i == sizeStr-1) /* réinit */
			{
				i=savInd; rechVal=-1; savInd=-1;
			}
		}

		delete[] pVals;
		delete[] pPoids;
		printf("\r\n%s\r\n", strrev(buf));
	}
}


bye...
Commenter la réponse de yann_lo_san
Messages postés
3830
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
19 novembre 2018
0
Merci
La solution proposée par yann_lo_san fonctionne, mais je la déconseille fortement ! Ce qui est demandé est un classique: on a un nombre, on le décompose via des "%" et des "/", c'est simple, rapide et efficace. Ca c'est pour la partie algorithmie. yann_lo_san précise tout de même que ce n'est pas nécessairement la meilleure approche. Ca reste une méthode alternative (et donc intéressante), mais il y a beaucoup de petites choses qui me gênent dans ce code.

@yann_lo_san:
Le problème de ta solution n'est pas "l'élégance". Ce qui est gênant, c'est que tu "tournes autour du pot" pour réaliser quelque chose de très directe. J'entends par là, que tu réalises de nombreuses opérations inutiles.

Analysons techniquement la méthode que tu proposes:
- Tout d'abord, tu représentes un nombre par une chaîne de caractères qui va être bien plus grande en mémoire que si ça avait été mis dans un entier (certes techniquement à ce stade ce n'est pas un vrai problème). Mais c'est tout de même mieux de montrer à un débutant d'utiliser les bons types. Ignorons ce détail, puisque tu précises bien que c'est pour montrer une méthode différente (ce qui est tout à ton honneur).
- Là où ça devient plus gênant: Tu fais un "strlen". On perd donc une passe sur la chaîne pour rien. En effet, scanf te retourne le nombre de caractères lus... Donc indirectement la taille de ta chaîne (c'est vrai pour un cas aussi simple).
- Ensuite, tu perds du temps à faire un "strrev" (en gros retourner la chaîne), alors qu'il suffit simplement de faire une boucle de la fin vers la début. En plus de cela, tu inverses la chaîne de nouveau à la fin pour la remettre à "l'endroit" (ce qui n'est pas nécessaire si tu ne la retournes pas au début).
- "const int MAXSIZENUM = (int)log10((double)INT_MAX)+1;" => Etant donné que les chiffres vont de 0 à 9, je pense qu'on peut se permettre de considérer qu'il y a 10 chiffres possibles et donc écrire directement "const int MAXSIZENUM = 10". Si on veut pinailler, on aurait pu aussi aller plus loin et écrire "const uint8_t MAXSIZENUM = 10" (ce qui équivaut à un unsigned char).

Quelques petits détails supplémentaires:
- pVals[i] = (int)buf[i]-48; => Le "cast" en int n'est pas nécessaire. (Je ne suis pas sur qu'un seul cast soit nécessaire d'ailleurs dans ton code).
- void main() => Attention, c'est officiellement "int main()". Le main retourne une valeur, qui est la code d'erreur lors de la fin du programme. On considère généralement le "void main" comme une extension non officielle et non standard (bien que supportée par certains compilateurs, si on n'active pas le mode "strict").

__________________________________________________________________________________________________
Améliorez votre expérience CodeS-SourceS avec ce plugin:
http://codes-sources.commentcamarche.net/forum/affich-10000111-plugin-better-cs-2#cptpingu-signature
Commenter la réponse de cptpingu
Messages postés
1137
Date d'inscription
lundi 17 novembre 2003
Dernière intervention
23 janvier 2016
0
Merci
Salut,

oui, oui, je prends toutes tes remarques à 100%.
Je m'était concentré sur le fait de ne faire qu'une seule boucle,
tout ce qui se trouve autour était codé "à la va vite"... pour construire l'exemple.

Par contre j'ai testé ton exemple 3 avec le std::map<> dont l'approche est bien sympa, mais il me semble qu'il y a une petite coquille

Si je saisi par exemple : 33442211
la sortie est :
1 0 1
2 2 3
3 6 7
4 4 5

les 2 dernières lignes sont inversées (comme triées)

Peut être que l'objet map<> tri ? a voir...

Bye...
Commenter la réponse de yann_lo_san
Messages postés
3830
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
19 novembre 2018
0
Merci
L'exemple 3, conserve l'ordre via l'operateur implicite "operator<" (utilisé par std::map en interne). Le std::map est une structure d'arbre ordonnée (donc triée).
Si on ne veut pas conserver l'ordre, il faut utiliser un std::unordered_map (mais alors aucun ordre n'est garanti, pas même l'ordre d'insertion). Je ne l'ai pas non plus utilisé car ce n'est disponible qu'en C++11.
La méthode qui se rapproche le plus de la consigne est évidemment la 2. Les autres méthodes ne respectent pas parfaitement l'affichage.

__________________________________________________________________________________________________
Améliorez votre expérience CodeS-SourceS avec ce plugin:
http://codes-sources.commentcamarche.net/forum/affich-10000111-plugin-better-cs-2#cptpingu-signature
Commenter la réponse de cptpingu

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.