Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1812 connectés 

  FORUM HardWare.fr
  Programmation
  C

  conversion nombre en chaine binaire

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

conversion nombre en chaine binaire

n°1455258
djobidjoba
Posté le 11-10-2006 à 10:55:19  profilanswer
 

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
mood
Publicité
Posté le 11-10-2006 à 10:55:19  profilanswer
 

n°1455289
_darkalt3_
Proctopathe
Posté le 11-10-2006 à 11:17:51  profilanswer
 

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
n°1455321
djobidjoba
Posté le 11-10-2006 à 11:32:40  profilanswer
 

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
n°1455333
_darkalt3_
Proctopathe
Posté le 11-10-2006 à 11:38:57  profilanswer
 

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
n°1455345
LetoII
Le dormeur doit se réveiller
Posté le 11-10-2006 à 11:44:22  profilanswer
 

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
n°1455365
Elmoricq
Modérateur
Posté le 11-10-2006 à 12:00:32  profilanswer
 

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
n°1455393
bb138
La vie est belle ...
Posté le 11-10-2006 à 12:55:52  profilanswer
 

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

n°1455405
Emmanuel D​elahaye
C is a sharp tool
Posté le 11-10-2006 à 13:14:00  profilanswer
 

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/
n°1455467
Elmoricq
Modérateur
Posté le 11-10-2006 à 14:29:32  profilanswer
 

bb138 a écrit :

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


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

n°1455560
djobidjoba
Posté le 11-10-2006 à 15:59:01  profilanswer
 

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
mood
Publicité
Posté le 11-10-2006 à 15:59:01  profilanswer
 

n°1455568
Elmoricq
Modérateur
Posté le 11-10-2006 à 16:06:57  profilanswer
 

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
n°1455570
_darkalt3_
Proctopathe
Posté le 11-10-2006 à 16:10:58  profilanswer
 

djobidjoba a écrit :

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


plaît-il ?


---------------
Töp of the plöp
n°1455574
_darkalt3_
Proctopathe
Posté le 11-10-2006 à 16:13:54  profilanswer
 


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


---------------
Töp of the plöp
n°1455603
djobidjoba
Posté le 11-10-2006 à 16:46:16  profilanswer
 

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.

n°1455607
Elmoricq
Modérateur
Posté le 11-10-2006 à 16:48:54  profilanswer
 

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
n°1455613
djobidjoba
Posté le 11-10-2006 à 16:52:09  profilanswer
 

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

n°1455619
Sve@r
Posté le 11-10-2006 à 16:56:04  profilanswer
 

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.
n°1455625
Elmoricq
Modérateur
Posté le 11-10-2006 à 17:01:13  profilanswer
 

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...

n°1455629
Sve@r
Posté le 11-10-2006 à 17:03:15  profilanswer
 

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.
n°1455632
Elmoricq
Modérateur
Posté le 11-10-2006 à 17:06:49  profilanswer
 

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
n°1455633
djobidjoba
Posté le 11-10-2006 à 17:07:03  profilanswer
 

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

n°1455635
Sve@r
Posté le 11-10-2006 à 17:09:38  profilanswer
 

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.
n°1455639
Elmoricq
Modérateur
Posté le 11-10-2006 à 17:12:03  profilanswer
 

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
n°1455643
Elmoricq
Modérateur
Posté le 11-10-2006 à 17:15:20  profilanswer
 

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
n°1455656
djobidjoba
Posté le 11-10-2006 à 17:21:12  profilanswer
 

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) ?

n°1455658
Elmoricq
Modérateur
Posté le 11-10-2006 à 17:23:23  profilanswer
 

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.

n°1455664
djobidjoba
Posté le 11-10-2006 à 17:26:58  profilanswer
 

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+

n°1455774
Sve@r
Posté le 11-10-2006 à 21:08:32  profilanswer
 

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.
n°1455830
Elmoricq
Modérateur
Posté le 12-10-2006 à 09:31:08  profilanswer
 

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

n°1490210
sideo
Hey, Tu prends l'apéro ?
Posté le 12-12-2006 à 13:47:25  profilanswer
 

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

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



---------------
@{epitech.}
n°1490221
Elmoricq
Modérateur
Posté le 12-12-2006 à 14:00:35  profilanswer
 

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]

n°1490297
sideo
Hey, Tu prends l'apéro ?
Posté le 12-12-2006 à 14:50:15  profilanswer
 

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

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C

  conversion nombre en chaine binaire

 

Sujets relatifs
Exo nombre premierConversion d'un hh:mm:ss en un FLOAT
Retourner une liste privée des multiples d'un nombresupprimer chaine de caractere dans un nom de fichier
[JS] transformer un nombre de seconde en minutes, heures, etc...fonction qui n'accepte que certains caracteres dans une chaine
"retourner" un nombreConversion XLS en CSV pb "," et ";"
parcourire un tableau et compter le nombre de valeurs d'une cléFaire une seule recherche de 2 types de chaine de caractère
Plus de sujets relatifs à : conversion nombre en chaine binaire


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR