afficher un nombre en base 2 [C] - C++ - Programmation
Marsh Posté le 27-09-2002 à 17:22:26
tricky a écrit a écrit : Voilà c très simple, je voudrais afficher la valeur binaire d'un nombre. Exemple 3=> 011 (pour ceux qui auraient pas compris ) Existe t'il un format spécial à mettre dans un printf ??? |
Ben j'en sais rien ...
Sinon tu peux faire :
Code :
|
Marsh Posté le 27-09-2002 à 17:22:26
je ne pense pas mais ca devrait pouvoir se faire rapidement :
Code :
|
Marsh Posté le 27-09-2002 à 17:23:42
tricky a écrit a écrit : Voilà c très simple, je voudrais afficher la valeur binaire d'un nombre. Exemple 3=> 011 (pour ceux qui auraient pas compris ) Existe t'il un format spécial à mettre dans un printf ??? |
Je sais que non pour printf mais une fnction le fait, le probleme c est que je me rappelle plus,il me semble que c est dans <conio.h>
(et tu peux convertir selon n importe quel base meme 7,99,...)
desole mais pour la fonction c plus le nom!
Marsh Posté le 01-10-2002 à 16:18:41
Tien salut carbon_14 !
Oui, il me semble qu'on avait déjà répondu à un problème dans ce genre ;o)
Marsh Posté le 01-10-2002 à 18:03:05
carbon_14 a écrit a écrit : Division Euclidienne. Fonction toute faite ? |
Non je parlais de conversion directe:
tu passes le nombre en base dix,et un char * et il te le converti n importe quel base jusqu a 16 mais j ai pas retrouver mon prog sur les graphs independant qui utilisait ca !
Marsh Posté le 01-10-2002 à 18:55:32
Dommmaaâaage ! On est preneur (ça peut servir).
Sprintf en hexa, c'est bon, mais en binaire, je connais pas (suis amateur !).
On va (re)lancer un concours (à moins de retrouver le vieux topic sur le sujet ? dix pages ?)
Marsh Posté le 02-10-2002 à 00:31:10
Un truc bricolé avant de se coucher (à vérifier, je dors assis)
{
char Chaine[64];
long ValDeci;
long lBase;
int iNbTour;
long Reste;
long Rapport;
ValDeci = 28; // exemple pour essayer
lBase = 2;
iNbTour = 0;
while (ValDeci >= lBase)
{
Rapport = ValDeci / lBase;
Reste = ValDeci - Rapport * lBase;
Chaine[iNbTour ++] = '0' + Reste;
ValDeci = Rapport;
};
// dernier digit (le plus important)
Chaine[iNbTour ++] = '0' + Rapport;
Chaine[iNbTour] = '\0';
strrev(Chaine); // retourne la chaîne
MessageBox(NULL, Chaine, "Chaine", MB_OK); // 11100 soit 28 en décimal
}
NB : si base > 10, l'"astuce" '0' + valeur numérique ne marche plus pour faire ABCDEF de l'hexa !
Marsh Posté le 02-10-2002 à 02:16:30
La version de carbon_14 fonctionne très bien, j'aurais juste quelques petites remarques :
carbon_14 a écrit a écrit : Reste = ValDeci - Rapport * lBase; |
En C (et C++), on peut utiliser l'opérateur % qui fournit directement le reste de la division. On a donc :
Code :
|
carbon_14 a écrit a écrit : // dernier digit (le plus important) |
Pour éviter de devoir faire le dernier chiffre "manuellement" (hors de la boucle), je pense qu'il est possible de remplacer le while (ValDeci >= lBase) par un while( ValDeci > 0 )
Marsh Posté le 02-10-2002 à 02:24:51
Pas standard:
Citation : Convert an integer to a string. |
Sinon, on va la faire nous-même.
Marsh Posté le 02-10-2002 à 09:08:33
Quelqu'un qui connait son C par coeur !
J'y pense jamais, car radix vaut généralement 10 => on oublie sa fonction universelle...
#include <stdlib.h>
char *itoa(int value, char *string, int radix);
radix specifies the base to be used in converting value; it must be between 2 and 36, inclusive. If value is negative and radix is 10, the first character of string is the minus sign (-).
Merci gatorette pour les éclaircissements, on en apprend toujours sur HFR. Y a des tas de trucs qui m'échappent, et je bricole comme ça vient . La fin de bouclage, j'y pensais ce matin dans le car, ça faisait pas "optimisé".
Marsh Posté le 02-10-2002 à 13:43:44
Oui, itoa yabon !
Citation : En C (et C++), on peut utiliser l'opérateur % qui fournit directement le reste de la division. On a donc :
|
Y'a plus simple et plus rapide : tester le dernier bit avec un ET binaire avec 1
Code :
|
Pas de division, pas de modulo ... ca torche quoi !
Bon le seul hic c'est que la l'ordre des bits va etre inverse (de droite a gauche au lieu gauche->droite) mais il suffit d'inverser le >>= par <<= et de remplacer le (nombre & 1) par (nombre & (1 << 31)) (pas fait pour + de lisibilite)
Marsh Posté le 02-10-2002 à 19:33:07
HelloWorld a écrit a écrit : Y'a plus simple et plus rapide : tester le dernier bit avec un ET binaire avec 1 |
C'est vrai que c'est plus rapide mais ça ne marche que si l'on veut faire du binaire. La solution proposée par carbon_14 marche pour n'importe quelle base. C'est vrai que ce n'était pas demandé mais c'est quand même bien sympathique.
D'ailleurs, J'ai une question pour les pros des compilateurs :
Il me semble que si l'on code j = i % 2;, la plupart des compilateurs sont suffisamment intelligents pour le transformer en j = i & 1;. De même, j = i / 2; sera transformé en j = i >> 1;. J'aimerais avoir confirmation là dessus.
Marsh Posté le 02-10-2002 à 19:42:15
HelloWorld a écrit a écrit : Oui, itoa yabon !
|
Pour avoir le nombre dans le bonne ordre, utilise le bout de code que j'ai écris plus haut ... (pour les entiers 32 bits) .
Marsh Posté le 03-10-2002 à 05:09:13
HelloWorld a écrit a écrit : Y'a plus simple et plus rapide : tester le dernier bit avec un ET binaire avec 1 |
Ne t'occupes pas de ça. (suite...)
gatorette a écrit a écrit : D'ailleurs, J'ai une question pour les pros des compilateurs : Il me semble que si l'on code j = i % 2;, la plupart des compilateurs sont suffisamment intelligents pour le transformer en j = i & 1;. De même, j = i / 2; sera transformé en j = i >> 2;. J'aimerais avoir confirmation là dessus. |
Je ne sui pas un pro, j'ai juste pas mal lu:
i= 0 -> i^=i :Oui (i entier, évidemment)
i%2 -> i&1 : Oui
i/2 -> i>>1 : Oui, à condition que i soit positif.
soit unsigned ... i;
soit assert(i>=0); Certains compilateurs s'en servent d'indice pour l'optimisation.
C'est valable pour toutes les autres puissance de 2 entières.
Ça n'est vrai que si le processeur calcule en base 2. Ce n'est pas forcément le cas, même si le risque est mince.
Il faut coder la vraie opération qu'on veut faire, et laisser les compilateurs faire ces optimisations basiques (connues depuis longtemps).
Avec l'avantage qu'elles n'ont lieu que si c'est vraiment équivalent.
Un topic où on en parlait: http://www.developpez.net/forums/viewtopic.php?t=1537
Marsh Posté le 03-10-2002 à 13:33:02
Citation : Pour avoir le nombre dans le bonne ordre, utilise le bout de code que j'ai écris plus haut ... (pour les entiers 32 bits) . |
Tu as lu trop vite ... en modifiant un tout petit peu, ca donne dans le bon ordre.
Mais je voulais pas surcharger le truc.
Citation : Ça n'est vrai que si le processeur calcule en base 2. Ce n'est pas forcément le cas, même si le risque est mince. |
!!!
Je sais que des processeurs de ce type ont ete concus mais etant donné qu'en base 2 c'est beaucoup beaucoup moins cher il me semblait qu'il n'avaient pas depasse le stade experimental.
Honnetement, le risque qu'il fase tourner cet algo sur une machine qui n'est pas en base 2 est ... nul. (l'interret d'avoir la representation binaire sur une machine qui ne l'est pas ?)
En revanche, je soulignerais plutot le probleme big-endian little-endian, probleme qui n'en est pas un ici.
Citation : Il faut coder la vraie opération qu'on veut faire, et laisser les compilateurs faire ces optimisations basiques (connues depuis longtemps). |
Ben moi je voulais tester l'etat du dernier bit et afficher un 1 ou un 0 en fonction ... ca me semble plus logique de proceder ainsi que de passer par un modulo.
Si je veux tester l'etat d'un bit, je fait un ET binaire.
Si je veux le reste d'une division, je fais un modulo.
Au fait j'y pense maintenant, mais y'a plus lisible pour mon code et mieux en plus :
shifter une variable mask au lieu de shifter la variable a tester (on preserve la variable a tester)
Code :
|
La c'est dans le bon ordre
Marsh Posté le 03-10-2002 à 23:26:38
HelloWorld a écrit a écrit : shifter une variable mask au lieu de shifter la variable a tester (on preserve la variable a tester)
|
Attention, il me semble que ça devrait être plutôt (nombre & mask) != 0 ou (nombre & mask) == mask.
Et juste une petite remarque, ton code doit connaître la taille maximum du nombre que l'on cherche à convertir (il me semble que la taille d'un int n'est pas définie), c'est un peu dommage. On peut peut être utiliser : int mask = (1 << ((sizeof(int) * 8) - 1));.
Concernant l'algorithme, je ne suis pas d'accord avec toi. L'opération que tu cherches à faire lors du passage d'une base à une autre, c'est récupérer le reste de la division. C'est pourquoi il est plus logique d'utiliser un modulo.
Dans le cas d'une conversion en binaire, le modulo peut être remplacé par un ET (et la division par un décalage), mais cela reste un cas particulier. De plus, le code devient bien moins lisible (il est moins facile de découvrir qu'il s'agit d'une conversion d'une base à une autre).
Marsh Posté le 04-10-2002 à 00:45:10
Ton code fait la supposition que les nombres sont réprésentés en binaire "classique".
C'est une toute petite suppostion, mais c'en est une quand même. On peut protéger:
Code :
|
On ne peut pas en faire du code générique, car ça ne marche pas avec des flottants, par exemple.
Un byte ne fait pas forcément 8 bits. La traduction correcte est "codet" ou "multiplet", pas "octet".
Code :
|
Pour le test, ceci suffit aussi:
Code :
|
Marsh Posté le 04-10-2002 à 16:46:45
Citation : Attention, il me semble que ça devrait être plutôt (nombre & mask) != 0 ou (nombre & mask) == mask. |
yep !
Le copier-coller est mon pire ennemi ... (j'ai deja passe des heures sur des erreurs comme ca)
Citation : Concernant l'algorithme, je ne suis pas d'accord avec toi. L'opération que tu cherches à faire lors du passage d'une base à une autre, c'est récupérer le reste de la division. C'est pourquoi il est plus logique d'utiliser un modulo. |
Dans mon esprit, je cherchais a tester l'etat de chaque bit, pas à convertir d'une base -> l'autre (je suis deja en base 2, je le reste en affichant en binaire)
De plus, je n'ai jamais cherche a faire une conversion de base (on me file un nombre en base 2 et je cree une chaine de caractere illustrant sa representation en base 2)
Citation : De plus, le code devient bien moins lisible (il est moins facile de découvrir qu'il s'agit d'une conversion d'une base à une autre). |
Une telle fonction peut derouter quelqu'un qui est peu habitue a manipuler les bits ... comme l'utilisation du modulo peut derouter quelqu'un d'autre ...
Selon moi, une petite portion de code comme cela, contenu dans une fonction bien nommee et accompagnee d'une ligne de commentaire explicite (// tester l'etat de chaque bit) est parfaitement lisible.
Ne serait-ce que le printf("1" ) else printf("0" ) donne une petite idee de ce qui se passe.
Le code de la fonction itoa ne doit pas etre plus simple que cela ...
Citation : Ton code fait la supposition que les nombres sont réprésentés en binaire "classique".
On ne peut pas en faire du code générique, car ça ne marche pas avec des flottants, par exemple.
|
byte = octet
J'ai pas fait de latin, mais la racine de octet c'est huit (un octogone a huit cotes)
Un octet a huit bits il me semble ...
Je comprends pas ce que tu veux dire par binaire classique.
Je connais que 2 notations binaires utilises : big (Motorola ...) et little (Intel ...) endian a savoir le bit de poids fort a droite / gauche (y'a le middle endian aussi mais je crois que aucune machine aujourd'hui ne l'utilise plus)
Pour ces 2 la, cet algo fonctionne
en effet, le cas de 2 par exemple : 1 << 1 sur Intel et 1 << 31 sur motorola
le meme algo affichera les 2 bonnes valeurs dans les 2 cas (tronque a 8 pour faire court):
"10000000" sur Motorola
"00000001" sur Intel
En revanche, en utilisant un modulo 2, ca va etre errone, ca va sortir dans les 2 cas la version Intel (si celle la qui a ete codee)
C'est pour cela que je prefere tester l'etat des bits.
Car meme sur une machine exotique genre middle endian, cet algo te sortira la bonne representation genre "00001000"
Je ne cherche pas a recoder le codage bianire d'un nombre decimal, je profite que le processeur l'ait fait pour moi en affichant le nombre tel qu'il est represente en memoire.
Meme pour les float je suis pas d'accord.
Cet algo imprime a l'ecran un nombre tel qu'il est represente en memoire.
La seule limitation de cette rapide implementation ke j'ai faite c'est qu'il ne se soucie pas de la taille et ne gere que des mots de 32 bits.
Compile sous DOS (ou un int vaut 16 bits) il ne marchera pas ...
C'est plutot le char qui ne fait pas toujours un byte, mais ca j'en suis pas sur. Il me semblait que char valait toujours un byte.
char est d'ailleurs sujet a confusion chez les debutants.
Il est considere comme un type caractere ce qui est faux (il y a toujours des surpris quand on dit que y'a pas besoin de fonction pour avoir le code ASCII d'un caractere char).
Un char, c'est un nombre 8 bits qui est utilise pour stocker les caracteres.
Mais il ne se limite pas aux caracteres.Il me semble plutot que la ou la taille est variable et propre a chaque compilo/plateforme, c'est pour le int qui fait soit short int soit long int.
Mais il est possible que je me trompe quelque part.
Marsh Posté le 05-10-2002 à 04:12:32
HelloWorld a écrit a écrit : "byte = octet" |
Ils ne sont donc pas vraiment synonymes. Le mot anglais n'a pas la racine 8.
Il y a donc des bytes de 6, 7, 9, 32 bits...
Citation : "affichant le nombre tel qu'il est represente en memoire." |
La question parle de valeur binaire, pas de représentation binaire.
Cela dit, il veut probablement la représentation...
Citation : "C'est plutot le char qui ne fait pas toujours un byte, mais ca j'en suis pas sur." |
En C/C++, sizeof(char) vaut par définition 1, c'est la plus petite unité adressable.
Son nombre de bits est CHARBITS de <limits.h>.
Marsh Posté le 05-10-2002 à 23:02:34
Citation : HelloWorld a écrit : |
Byte != octet !!
Je suis quasiment sur que byte == octet.
http://www.amgitweb.com/definitions/octet.htm
Tu confonds pas plutot avec un mot memoire (WORD) ?
Un WORD sur un processeur 8 bits vaut 8 bits, sur un 16 bits 16 ...
Si le taille d'un byte est indeffinie, comment interpréter des valeurs telles que "512 kilo byte de memoire cache" ?
Citation : La question parle de valeur binaire, pas de représentation binaire. |
Valeur binaire n'a pas de sens pour moi.
10 en decimal ou en binaire a la meme valeur : il vaut 10 en (representation) decimal ce qui est equivalent à 1010 en binaire ...
Je dirais plutot valeur en binaire, sous entendu valeur d'un nombre representée en binaire.
Et meme, la "valeur binaire" d'un nombre est directement liee a la representation binaire utilisée, a savoir little/big endian.
Pour trancher entre ces 2 "valeurs binaires" possibles pour un même nombre, le mieux est de laisser faire le processeur (adopter sa representation)
Marsh Posté le 06-10-2002 à 02:08:28
Dans l'immense majorité des cas un byte fait 8 bits comme l'octet, mais pas toujours.
http://www.isty-info.uvsq.fr/~rume [...] 6.html#q_2
http://www.comeaucomputing.com/techtalk/#bitsinbyte
Pour le binaire, il s'agit bien effectivement de nuancer entre:
-La représentation binaire (supposée) interne au processeur.
-La représentation de la valeur arithmétique en binaire selon différent formats:
0110 nombre de chiffres fixe
110 chiffres utiles seulement
-110 négatif
Marsh Posté le 06-10-2002 à 05:31:15
Citation : Dans l'immense majorité des cas un byte fait 8 bits comme l'octet, mais pas toujours. |
"Ce programme necessite 1 mega byte de memoire vive*"
* 1 byte = 1024 bits
Arf, une telle fourberie, le jour ou ca m'arrive, je pete un plomb.
Font ch*** ces anglais
Marsh Posté le 06-10-2002 à 10:32:16
Citation : un byte est un multiplet d'au moins 7 bits capables de stocker un caractère |
le 2° lien donne par musaran invalide ta definition ...
=> En C/C++, un byte vaut au moins 8 bits
=> certains processeurs considere que 1 byte = 6 bits
Citation : puisque c'est à la mode ici de balancer 500 versions pour faire un hello world... |
Ton code a 2 erreurs :
- il ne fonctionne que pour le little endian (Intel)
- meme pour le little endian il affiche les bits dans le mauvais ordre (affiche comme du big endian)
Marsh Posté le 06-10-2002 à 11:12:57
ben j'etais mal réveiller.
et la définition du byte varie, pour le C++ c'est une condition d'implémentation
Code :
|
qunad aux differents systemes de stockage, c'est la un problème. meme si les opérateurs de traitements de bit sont bien définis, c'est sur que c'est aps portable. de toutes façons, si on veut vraiment faire un programme portable, il vaut mieux les éviter et faire des jolies divisions.
Edit; j'oubliais le printf("%x", c). c'est ce qu'il y a de mieux
Marsh Posté le 06-10-2002 à 13:02:49
Ah le dimanche matin c'est vraiment dur ...
mask= 1 << CHAR_BIT;
c'est mask= 1 << (CHAR_BIT - 1);
On retrouve a peu pres le code deja donné ...
Citation : quand aux differents systemes de stockage, c'est la un problème |
Moi je trouve ce code tout a fait portable ... il donnera la bonne representation binaire en fonction du processeur, meme si c'est une representation inconnue ...
Citation : si on veut vraiment faire un programme portable, il vaut mieux les éviter et faire des jolies divisions. |
... contrairement a des divisions qui ne permettent d'implementer qu'une seule representation binaire a la fois (ou alors il faut se faire chier a detecter le type de representation et coder au cas par cas ... et faut etre sur de toutes les connaitre).
Citation : j'oubliais le printf("%x", c). c'est ce qu'il y a de mieux |
Ca donne pas plutot l'hexa ca ...
Marsh Posté le 06-10-2002 à 13:22:42
ouais c'est de l'hexa et alors si t'es capable de lire du binaire tu devrais pouvoir lire de l'hexa
surtout qu'au dela de 8bits, les 0/1 ca commence a etre bordélique
edit: mais les opérations de décalage sont définies que pour les types entiers non-signés, apres le comportement (pour les non signés) n'est pas dicté par la norme
Marsh Posté le 06-10-2002 à 13:36:02
Citation : ouais c'est de l'hexa et alors si t'es capable de lire du binaire tu devrais pouvoir lire de l'hexa |
la question est d'afficher en binaire.
Citation : edit: mais les opérations de décalage sont définies que pour les types entiers non-signés, apres le comportement (pour les non signés) n'est pas dicté par la norme |
[genre j'ai tout prevu]
C'est pour cela que dans mon algo c'est le mask qui est shifté et pas la variable ...
[/genre j'ai tout prevu]
Marsh Posté le 06-10-2002 à 14:23:29
Qu'est ce tu veux que je te dise, que si on veut afficher en binaire c'est printf("%x", ...) qu'il faut utiliser ?
La fonction a ete donnee : c'est itoa.
Mais on est parti a titre de curiosite a une implementation maison.
C'est tres bien, on a fait le tour de plein de truc, depuis le codage en base 2 jusqu'a la norme C. Ca permet d'aller un peu plus loin a partir d'une question bateau posee pour la enieme fois.
Un algo a peu pres correct est pondu.
Toi tu deboules, et apres plusieurs essais, tu nous pond ... le meme algo, mais en moins bien.
J'ai essayer de te le faire remarquer avec un trait d'humour pour ne pas que tu te vexes et voila que tu gueules apres le fait de donner son algo a soit alors que c'est toi qui relance le post en debalant le tient.
Ce n'est pas _mon_ algo.
J'ai emis une premiere idee, que j'ai corrige suite aux diverses remarques et musaran a paufine le tout. C'est un travail collectif.
Je peux rien te dire de plus a part relie le thread depuis le debut et tu verras que tes posts ne font que reprendre ce qui a ete dit.
Marsh Posté le 07-10-2002 à 02:55:15
Toujours caractériel, Taz ?
Fait pas gaffe au nombre de posts, on aime bien chipoter des fois.
Citation : les opérations de décalage sont définies que pour les types entiers non-signés, apres le comportement (pour les [non] signés) n'est pas dicté par la norme" |
Il me semble que seul >> sur un nombre négatif est dépendant de l'implémentation. Mais là je suis pas sûr.
Donc, HelloWorld, ton code n'est pas bon, puisqu'il décales à droite un int signé vraisemblablement négatif.
Ce que j'aimerais savoir, c'est si << est bien défini comme décalant vers le poids fort.
re-:ange:
Voilà le mien, je pense qu'il est blindé:
Code :
|
Musaran a écrit a écrit :
|
C'est CHAR_BIT, et personne ne me reprends... qu'est-ce qu'on peut mettre comme bêtises impunément !
Marsh Posté le 27-09-2002 à 17:07:26
Voilà c très simple, je voudrais afficher la valeur binaire d'un nombre.
Exemple 3=> 011 (pour ceux qui auraient pas compris )
Existe t'il un format spécial à mettre dans un printf ???
Message édité par Tricky le 27-09-2002 à 17:08:13