conversion nombre en chaine binaire - C - Programmation
Marsh Posté le 11-10-2006 à 11:17:51
valeur; |
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
Marsh Posté le 11-10-2006 à 11:38:57
J'ai fait une erreur:
valeur; |
Marsh Posté le 11-10-2006 à 11:44:22
admettons qu'on travaille en 32 bits:
Code :
|
Après on peut rafiner pour virer les 0 inutiles.
Marsh Posté le 11-10-2006 à 12:00:32
Ou alors, supposons que l'on travaille de manière portable
Code :
|
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
Marsh Posté le 11-10-2006 à 12:55:52
ReplyMarsh 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 ?
Marsh Posté le 11-10-2006 à 14:29:32
ReplyMarsh 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 :
|
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 :
|
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.
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 ?
Marsh Posté le 11-10-2006 à 16:13:54
ReplyMarsh 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.
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) |
Ah, mince. La solution que j'ai postée, qui fonctionne et est légale vis-à-vis du langage, n'existe pas.
Spoiler :
|
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
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 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
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 )
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...
Marsh Posté le 11-10-2006 à 17:03:15
Elmoricq a écrit : edit : CHAR_BIT est défini dans limits.h |
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)" ???
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.
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
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...
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) |
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.
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.
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...
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 :
|
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) ?
Marsh Posté le 11-10-2006 à 17:23:23
djobidjoba a écrit : error: 'for' loop initial declaration used outside C99 mode |
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.
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+
Marsh Posté le 11-10-2006 à 21:08:32
Elmoricq a écrit : Ah vi, pas idiot, ça !
|
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
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. |
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...
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 |
Le temps de réfléchir, de tester et de "corriger" (toujours pas compris le comportement avec short), et j'ai corrigé mon message.
Marsh Posté le 12-12-2006 à 13:47:25
convertir un chiffre en binaire (de l'ascii... ce que tu veux...) :
Code :
|
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.
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...
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