conversion nombre en chaine binaire

conversion nombre en chaine binaire - C - Programmation

Marsh Posté le 11-10-2006 à 10:55:19    

Bonjour, en gros je cherche a convetir 11 (0xB) en "1011".  
J'ai l'algo suivant :


 while (valeur != 0)
 {
    tmp[i] = 48 + (valeur % 2);
    valeur = valeur /2;
    i++;
 }


Ca marche dans plusieurs cas, sauf pour 11 (evidemment ^^)
en effet :


11%2 = 1, 11/2 = 5.5
 5%2 = 1,  5/2 = 2.5
 2%2 = 0,  2/2 = 1
 1%2 = 1,  1/2 = 0
> stop
 
"1101" = 13 <> 11


 
une idée ?
merci


Message édité par djobidjoba le 11-10-2006 à 10:56:23
Reply

Marsh Posté le 11-10-2006 à 10:55:19   

Reply

Marsh Posté le 11-10-2006 à 11:17:51    

valeur;
chaine[16]; // pour un binaire sur 16 bits
 
pour i=15 à 0
   si (valeur - 2^i >= 0)
   alors chaine[i] = 1
   sinon chaine[i] = 0
fin pour


Message édité par _darkalt3_ le 11-10-2006 à 11:24:47

---------------
Töp of the plöp
Reply

Marsh Posté le 11-10-2006 à 11:32:40    

salut, merci
mais .. admettons, on travail sur 4 bits, valeur =12
 
12 - 2^3 = 4 -> '1'
12 - 2^2 = 8 -> '1'
12 - 2^1 = 10 -> '1'
12 - 2^0 = 11 -> "1"
 
1111 :/


Message édité par djobidjoba le 11-10-2006 à 11:35:26
Reply

Marsh Posté le 11-10-2006 à 11:38:57    

J'ai fait une erreur:

valeur;
chaine[16]; // pour un binaire sur 16 bits
 
pour i=15 à 0
   si (valeur - 2^i >= 0)
      alors
         chaine[i] = 1
         valeur = valeur - 2^i
      sinon chaine[i] = 0
fin pour


---------------
Töp of the plöp
Reply

Marsh Posté le 11-10-2006 à 11:44:22    

admettons qu'on travaille en 32 bits:

Code :
  1. char temp[33];
  2. temp[32] = '\0';
  3. unsigned int mask = 0x80000000;
  4. for(int i = 0; i <32;++i)
  5. {
  6.   if(value & mask)
  7.   {
  8.      temp[i] = '1';
  9.   }
  10.   else
  11.   {
  12.     temp[i] = '0';
  13.   }
  14.   mask >> 1;
  15. }


 
Après on peut rafiner pour virer les 0 inutiles.


Message édité par LetoII le 11-10-2006 à 11:46:01
Reply

Marsh Posté le 11-10-2006 à 12:00:32    

Ou alors, supposons que l'on travaille de manière portable :o
 

Code :
  1. char *inttobits(int value)
  2. {
  3.    unsigned size = CHAR_BIT * sizeof(int);
  4.    char *str = calloc(size+1, sizeof(char));
  5.  
  6.    if ( str )
  7.    {
  8.        int mask = ~0 << (size - 1);
  9.  
  10.        for(unsigned bit = 0; bit < size; ++bit)
  11.        {
  12.            str[bit] = (value & mask) != 0 ? '1' : '0';
  13.            value<<=1;
  14.        }
  15.    }
  16.  
  17.    return str;
  18. }


 
 
edit : CHAR_BIT est défini dans limits.h
 
edit 2 : je me demande s'il n'y a pas plus élégant pour initialiser le masque... j'avais pensé à "~(~0 >> 1)", mais ce qui est inséré par décalage à droite est dépendant de l'implémentation :/

Message cité 1 fois
Message édité par Elmoricq le 11-10-2006 à 12:07:51
Reply

Marsh Posté le 11-10-2006 à 12:55:52    

Juste un petit reproche : unsigned n'est pas un type.

Reply

Marsh Posté le 11-10-2006 à 13:14:00    

bb138 a écrit :

Juste un petit reproche : unsigned n'est pas un type.


Ah bon ? C'est quoi ? Une nouvelle danse ?


Message édité par Emmanuel Delahaye le 11-10-2006 à 13:14:20

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 11-10-2006 à 14:29:32    

bb138 a écrit :

Juste un petit reproche : unsigned n'est pas un type.


 
http://images.imagehotel.net/9517095a37.jpg

Reply

Marsh Posté le 11-10-2006 à 15:59:01    

re,
 
bon, je suis partis sur la base de _darkalt3_, que je remercie ainsi que les autres biens sûr.
pour les autres solutions, mon niveau ne permet pas de les debugger et ma plateforme d'execution est allergique aux allocations mémoires.
 
voila le prog final qui permet de :
donner la représentation binaire de la valeur d'un caractère représentant un quartet hexa (ouf)
ex : hexatobits('b')="1011"
 

Code :
  1. char *hexatobits(unsigned char nbhexa)
  2. {
  3. int i,value=0;
  4. static char str[4];
  5. if ((int)(nbhexa) < 58)
  6.  value = (int)(nbhexa) - 48;
  7. else
  8.  value = (int)(nbhexa) - 97 + 10;
  9. for (i=3;i>=0;i--)
  10. {
  11.  if ((value - puiss(2,i))>=0)
  12.  {
  13.   str[3-i] = '1';
  14.   value = value - puiss(2,i);
  15.  }
  16.  else
  17.   str[3-i] = '0';
  18. }
  19. str[4]='\0';
  20. return str;
  21. }
  22. int puiss(int x, int n)
  23. {
  24.     int i, puiss = 1;
  25.     for (i=1; i<=n; i++) puiss = puiss * x;
  26.     return puiss;
  27. }

Message cité 2 fois
Message édité par djobidjoba le 11-10-2006 à 16:02:56
Reply

Marsh Posté le 11-10-2006 à 15:59:01   

Reply

Marsh Posté le 11-10-2006 à 16:06:57    

Si tu retournes l'adresse d'une variable locale, tu t'exposes à de graves problèmes : le comportement est en effet indéfini.
 
Si ce que tu recherches c'est, toujours, les 4 derniers bits d'un nombre, alors une solution simple c'est :

Code :
  1. void lastfourbits(int value, char bits[5])
  2. {
  3.     int mask = 0x01;
  4.     for(unsigned i = 0; i < 4; ++i)
  5.     {
  6.         bits[3-i] = (value & mask) != 0 ? '1' : '0';
  7.         value>>=1;
  8.     }
  9.     bits[4] = '\0';
  10. }


 
 
Quant à ta fonction puiss(), il se passe quoi si n est négatif, ou très grand ?
C'est mieux d'utiliser pow() je pense.

Message cité 1 fois
Message édité par Elmoricq le 11-10-2006 à 16:08:36
Reply

Marsh Posté le 11-10-2006 à 16:10:58    

djobidjoba a écrit :

ma plateforme d'execution est allergique aux allocations mémoires.


plaît-il ?


---------------
Töp of the plöp
Reply

Marsh Posté le 11-10-2006 à 16:13:54    


+1 avec Elmoricq; en + ton static là ca fait crade.


---------------
Töp of the plöp
Reply

Marsh Posté le 11-10-2006 à 16:46:16    

pour l'histoire de la variable local, effectivement gcc me sortait un warning  (le meme que le tiens in english)
les docs par ci par là, mon indiquées que j'avais 2 soluces :
- var globale
- static
- renvoyer l'adresse donc pointeur+alloc
 
pour l'alloc c'est pas simple sur ma plateforme qui est un terminal bancaire. Os  + lib gcc  + code existant tout pourris  
au moindre bit non controlé c reboot 5 phases plus loin.
 
pour pow() je connaissais pas.

Reply

Marsh Posté le 11-10-2006 à 16:48:54    

djobidjoba a écrit :

pour l'histoire de la variable local, effectivement gcc me sortait un warning  (le meme que le tiens in english)
les docs par ci par là, mon indiquées que j'avais 2 soluces :
- var globale
- static
- renvoyer l'adresse donc pointeur+alloc


 
Ah, mince. La solution que j'ai postée, qui fonctionne et est légale vis-à-vis du langage, n'existe pas. :(
 
 

Spoiler :

[:petrus75]


Message édité par Elmoricq le 11-10-2006 à 16:49:11
Reply

Marsh Posté le 11-10-2006 à 16:52:09    

dsl Elmoricq, j'ai bien vu ta répionse et je pense que c'est bien la bonne solution pour une procédure.
je dois implémenter une fonction pour eviter de tout chambouler avant

Reply

Marsh Posté le 11-10-2006 à 16:56:04    

Elmoricq a écrit :

Quant à ta fonction puiss(), il se passe quoi si n est négatif, ou très grand ?
C'est mieux d'utiliser pow() je pense.


 
C'est bien d'en parler mais, à mon avis, faut pas accorder à ce soucis plus d'importance que ça n'en a réellement. Si tu contrôles tes paramètres toi-même, tu sais bien que tu ne mettras pas de "n" négatif ou très grand. Au pire tu déclares "n" comme unsigned short et "puiss()" comme "long" (ou "unsigned long" voire "double" selon le besoin initial) et puis voilà. En revanche, si tu fais débuter "i" à "2", tu gagnes en perfos pour le même résultat  [:ddr555]
 
Je ne sais pas comment fonctionne "pow()" mais étant donné qu'elle est capable de calculer des nombres à une puissance fractionnaire et/ou négative, il est fortement probale (voire quasiment certain) qu'elle passe par les logarithmes donc je pense que son calcul sera plus long que la boucle "for" de djobidjoba (super le pseudo  :pt1cable: )


Message édité par Sve@r le 11-10-2006 à 16:59:59

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 11-10-2006 à 17:01:13    

J'avais lu le code source de la fonction dans la glibc, et il me semble que, en effet, la fonction utilise les logarithmes, aux optimisations prêts (des tests sont faits pour optimiser selon certains critères pour booster).
 
Après je ne connais pas les impacts de performances sur la cible de djobidjoba. Dans tous les cas il faut vérifier la plage d'utilisation de la fonction et vérifier aussi que le type int suffit...

Reply

Marsh Posté le 11-10-2006 à 17:03:15    

Elmoricq a écrit :

edit : CHAR_BIT est défini dans limits.h
 
edit 2 : je me demande s'il n'y a pas plus élégant pour initialiser le masque...


Il te suffit d'écrire

mask=1 << (size - 1)


puis de décaler "mask" vers la droite à chaque bit testé...
 

Elmoricq a écrit :

j'avais pensé à "~(~0 >> 1)", mais ce qui est inséré par décalage à droite est dépendant de l'implémentation :/


Même si tu rajoutes de l'unsigned en cast style "~(~(unsigned short)0 >> 1)" ???

Message cité 1 fois
Message édité par Sve@r le 11-10-2006 à 17:06:46

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 11-10-2006 à 17:06:49    

Le problème du décalage vers la droite sur un entier signé, c'est que le remplissage se fait avec des 1 ou des 0, et que cela dépend entièrement de l'implémentation (et je ne suis pas sûr que ta solution de modifier le masque à chaque itération soit plus élégante ;) ).
 
Sinon une autre solution est tout simplement de procéder de la droite vers la gauche, en fait. On crée un masque avec le bit de poids faible à 1, et on décale le nombre à parser d'autant de bits à tester... c'est surement plus chouette, et remplir la chaîne de destination de la droite vers la gauche n'est pas contraignant puisqu'on en connait exactement la taille. [:dawa]
 

Message cité 2 fois
Message édité par Elmoricq le 11-10-2006 à 17:10:07
Reply

Marsh Posté le 11-10-2006 à 17:07:03    

0xF -> 15 -> 15^3 = 3375 la valeur max.
je me rappel plus des valeurs max/min d'un int mais ca doit rentrer

Reply

Marsh Posté le 11-10-2006 à 17:09:38    

Elmoricq a écrit :

Le problème du décalage vers la droite sur un entier signé, c'est que le remplissage se fait avec des 1 ou des 0, et que cela dépend entièrement de l'implémentation


 
T'es certain ??? Je pensais que le remplissage se faisait avec du "1" si (et seulement si)
- l'élément était signé
- le bit de signe était à "1"
afin de garder l'extension du bit de signe...


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 11-10-2006 à 17:12:03    

Sve@r a écrit :

T'es certain ??? Je pensais que le remplissage se faisait avec du "1" si (et seulement si)
- l'élément était signé
- le bit de signe était à "1"
afin de garder l'extension du bit de signe...


 
Pas d'après le K&R (pour les nombres négatifs) :/
J'avais trouvé une doc tout à l'heure qui décrivait les deux logiques possibles, mais globalement tout ce que j'ai pu trouver sur le sujet fait état du même comportement.

Message cité 1 fois
Message édité par Elmoricq le 11-10-2006 à 17:17:03
Reply

Marsh Posté le 11-10-2006 à 17:15:20    

Sve@r a écrit :

Même si tu rajoutes de l'unsigned en cast style "~(~(unsigned short)0 >> 1)" ???


Ah vi, pas idiot, ça !
 
Par contre faut mettre unsigned int, et non short, sinon je ne sais pas ce qui se passe au moment du cast en entier, mais le 1 baladeur est perdu (j'ai pas d'idée pour expliquer ce comportement).
 
Donc en fait, ceci :

int mask = ~((~(unsigned int)0) >> 1);


fonctionne nickel. [:romf]
 
edit : je pige pas ce qui se passe quand je décale un unsigned short... il y a dans le mécanisme du décalage à droite et/ou dans le cast quelque chose que je ne maîtrise pas je pense, si quelqu'un a l'explication je suis preneur, parce que si je me sers de notre fonction pour tester, avec "int value = ~(unsigned short)0 >> 1", je n'obtiens que des 1...

Message cité 1 fois
Message édité par Elmoricq le 11-10-2006 à 17:25:04
Reply

Marsh Posté le 11-10-2006 à 17:21:12    

je ne connaissais pas ces déclarations en plein code, j'ai donc moi aussi essayé mais visiblement mon compilo (gcc 4.3) n'aime pas
ici par ex :

Code :
  1. for (int i=1; i<=n; i++) puiss = puiss * x;


error: 'for' loop initial declaration used outside C99 mode
 
ya une option à spécifier ( c plus pour ma culture général je l'avoue) ?

Reply

Marsh Posté le 11-10-2006 à 17:23:23    

djobidjoba a écrit :

error: 'for' loop initial declaration used outside C99 mode
 
ya une option à spécifier ( c plus pour ma culture général je l'avoue) ?


 
Comme le message d'erreur l'indique, c'est une fonctionnalité de la norme C99, or par défaut, gcc compile en C90, qui n'accepte les déclarations qu'en début de bloc (donc à l'intérieur d'un if ça fonctionne en C90, mais pas au beau milieu d'une boucle for).
 
Tu peux ajouter l'option "-std=c99" pour avoir accès aux fonctionnalités de la norme C99.

Reply

Marsh Posté le 11-10-2006 à 17:26:58    

héhé ca c'est bon :)
je vais me la péter dans le bureau a côté avec mon option c99 et je reviens.
non dans dec merci pour l'info ;)
a+

Reply

Marsh Posté le 11-10-2006 à 21:08:32    

Elmoricq a écrit :

Ah vi, pas idiot, ça !
 
Par contre faut mettre unsigned int, et non short, sinon je ne sais pas ce qui se passe au moment du cast en entier, mais le 1 baladeur est perdu (j'ai pas d'idée pour expliquer ce comportement).
 
Donc en fait, ceci :

int mask = ~((~(unsigned int)0) >> 1);


fonctionne nickel. [:romf]


Tiens ? T'as édité ton post car la dernière fois que je l'ai lu (sans pouvoir y répondre) tu disais que c'était une niaiserie  :D
Sinon j'ai aussi une autre solution.

long mask=-1;


En effet, pourquoi se chercher la complication à ne vouloir qu'un seul 1 en début de position binaire. Tu en mets de partout bien que les autres soient inutiles...
 

Elmoricq a écrit :

je pige pas ce qui se passe quand je décale un unsigned short... il y a dans le mécanisme du décalage à droite et/ou dans le cast quelque chose que je ne maîtrise pas je pense, si quelqu'un a l'explication je suis preneur, parce que si je me sers de notre fonction pour tester, avec "int value = ~(unsigned short)0 >> 1", je n'obtiens que des 1...


D'entrée je vois pas - Je regarderai demain à tout hasard...
 

Elmoricq a écrit :

Sinon une autre solution est tout simplement de procéder de la droite vers la gauche, en fait. On crée un masque avec le bit de poids faible à 1, et on décale le nombre à parser d'autant de bits à tester... c'est surement plus chouette, et remplir la chaîne de destination de la droite vers la gauche n'est pas contraignant puisqu'on en connait exactement la taille. [:dawa]


Effectivement, en y réfléchissant c'est moins idiot de décaler la valeur à tester plutôt que de se prendre la tête à vouloir créer un masque avec un 1 flottant. D'ailleurs, pourquoi même créer un masque ? Tu compares le bit du nombre à tester avec "1" et puis basta.
 

Elmoricq a écrit :

Pas d'après le K&R (pour les nombres négatifs) :/


Evidemment, quand on cite l'argument ultime... Faudra vraiment que je le lise un jour ce livre... :sol:


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 12-10-2006 à 09:31:08    

Sve@r a écrit :

Tiens ? T'as édité ton post car la dernière fois que je l'ai lu (sans pouvoir y répondre) tu disais que c'était une niaiserie  :D


 
Le temps de réfléchir, de tester et de "corriger" (toujours pas compris le comportement avec short), et j'ai corrigé mon message. :D

Reply

Marsh Posté le 12-12-2006 à 13:47:25    

convertir un chiffre en binaire (de l'ascii... ce que tu veux...) :

Code :
  1. printf("%c ", ( x & (1 << y) ) ? '1' : '0' )



---------------
@{epitech.}
Reply

Marsh Posté le 12-12-2006 à 14:00:35    

Mmm, déterrer un post, dont la question a -je pense- été bien débattue, pour fournir une solution incomplète et déjà donnée, je ne suis pas sûr que ce soit... pertinent. [:doc petrus]

Reply

Marsh Posté le 12-12-2006 à 14:50:15    

Sorry je croyais que le dernier post datait de 10/12.. Bref le code est pas incomplet at all...

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed