Passer d'une chaine de chiffre à une chaine de bit??? - Programmation
Marsh Posté le 01-08-2001 à 08:56:33
?
Un caractère est codé dans un octet.
Le caractère de code ASCII 16 est représenté sous la forme binaire 00010000, celui de code 32 00100000.
Si on en a besoin, on peut manipuler les bits du caractère avec les opérateurs C ad-hoc, ceci pour chaque caractère de la chaîne.
Quel est le problème/besoin précisément ??
Ce serait d'avoir char TableBits[288] avec un caractère 1 ou zéro pour chaque bit ?
Marsh Posté le 01-08-2001 à 09:50:57
Tout à fait, mon pb est d'obtenir la chaine de bit de mon nombre composé de 35 chiffres...J'ai:
char Tab[36]="12345678901234567890123456789012345"
(je le manipule sous forme de chaine de caractère car il est trop gros..)
J'aimerai obtenir TabBit[], la représentation en bits du nombre 123456...45
TabBit[]="...1001011101000101...
Voilà...
Marsh Posté le 01-08-2001 à 09:57:33
tu veux la réprésentation chiffre par chiffre ou la valeur complète en bits??
dans les 2 cas, une petite fonction de conversion ne doit pas etre très compliquée
Marsh Posté le 01-08-2001 à 10:13:53
Je cherche à avoir la valeur complète en bits...Si tu as des idées pour une fonction...
Marsh Posté le 01-08-2001 à 10:38:41
Ton nombre de 36 chiffres, tu le récupère ou tu le saisie ?
Ne peux-tu pas le stocker plutot en Hexa-decimal, dans ta chaine ?
Si oui, la conversion en chaine de bit est très simple.
Tu fais une fonction qui parcourt ta chaine, et qui pour chaque caractere (0 a F) te retourne une chaine de huit caractères (00000000 a 11111111). Et tu concatènes le tout !
Si non, je vais y réfléchier )
Marsh Posté le 01-08-2001 à 11:04:49
Bon, je ne devais pas encore être bien réveillé, quand j'ai répondu !
La fonction doit te retourner une chaine de 4 caractères (0000 à 1111), et non 8. Un caractere Hexa = 1 quartet !
Honte sur moi !
Marsh Posté le 01-08-2001 à 11:10:35
TotOOntHeMooN a écrit a écrit : Ton nombre de 36 chiffres, tu le récupère ou tu le saisie ? Ne peux-tu pas le stocker plutot en Hexa-decimal, dans ta chaine ? Si oui, la conversion en chaine de bit est très simple. Tu fais une fonction qui parcourt ta chaine, et qui pour chaque caractere (0 a F) te retourne une chaine de huit caractères (00000000 a 11111111). Et tu concatènes le tout ! Si non, je vais y réfléchier ) |
apparemment il cherche à convertir la valeur représentée par la chaine
tiens question conne : c'est quoi le language??
tu cherches juste l'algo?
Marsh Posté le 01-08-2001 à 11:23:10
Et bien justement, en passant la chaine en hexa, et en convertissant caractere par caractere en binaire, et en concaténant le tout, ca te donne bien la valeur du nombre représenté par la chain!
exemple :
decimal : 123
hexa : 7B
binaire : B = 1011
7 = 0111
7B = 01111011
C'est magique!!! Non...
En fait c'est logique et c'est surtout à ca que sert l'hexadécimal ; Convertir facilement le decimal en binaire.
Je pense donc bien répondre à la question.
Marsh Posté le 01-08-2001 à 11:28:19
Pour le language, je pense que c'est en c, vu l'indication "char Table[26]", mais le mieux et de donner des algos, car c'est portable et compréhensible de tous.
Marsh Posté le 01-08-2001 à 11:29:16
En C "basique", on pourrait écrire
char Chaine[36]; // 35 caractères
char Finale[281]; // autant qu'il en faut
char Bin[] = {"00000000", "00000001", ..., ...., "00001001"}; //0 à 9
int iVal;
Finale[0] = '\0';
for (iC = 0; iC < strlen(Chaine); iC ++)
{
iVal = Chaine[iC] - '0'; // 0 pr "0", 9 pour "9"
strcat(Finale, Bin[iVal]);
}
D'après la méthode TotOOntHeMooN, une fonction pratique est sprintf() car il y a un format HEXA (je croyais qu'il y avait aussi binaire direct, c'est pas le cas).
Marsh Posté le 01-08-2001 à 11:33:22
le language utilisé est le C++...
La solution de Totoonthemoon parait performante, mais, question stupide, comment je peut convertir la chaîne de caractère représentant mon nombre en hexa?
Marsh Posté le 01-08-2001 à 11:37:21
En réponce à CARBON_14
Du à mon erreur (la nuit à été longue), il faut remplacer
char Bin[] = "00000000", "00000001", ..., ...., "00001001"};
par
char Bin[] = "0000", "0001", ..., ...., "1001"};
Marsh Posté le 01-08-2001 à 11:43:40
En fait, je ne suis toujours par réveillé, car la methode que tu propose ne doit pas fonctionner, CARBON_14...
En effet, tu concatène des nombres décimaux entre eux, ce qui ne peux pas fonctionner !
Marsh Posté le 01-08-2001 à 11:47:06
effectivement, ce n'est pas une méthode qui fonctionne...dommage
Marsh Posté le 01-08-2001 à 12:03:21
C'est pour ca, que je te demande si tu la saisie ou si tu la récupère...
Si tu la saisie, alors fait le en hexa et le tour est joué !
Si tu la récup tel quel, tu reviens au même problème qu'au départ... Dans ce cas la, je réfléchi à une autre méthode (des souvenirs de math) et je te le dis !
Marsh Posté le 01-08-2001 à 12:32:37
Désolé d'avoir mal compris. C'est pas la représentation binaire de chaque caractère (digit) qui est demandé (comme je croyais à tort) mais combien fait en binaire le nombre
123456789012345678901234567890123456789.
Si on se base sur la "définition", si on divise le nombre par deux, le reste est le dernier caractère (0 ou 1).
Le nombre obtenu, on le divise par deux. L'avant dernier caractère étant le reste.
129 / 2 = 64; 129 - 2 * 64 = 1
64 / 2 = 32; 64 - 2 * 32 = 0;
etc...
2 / 2 = 1;
on a alors 129 = 10000001 en binaire.
Si le nombre est trop grand pour rentrer dans une variable du C, il faut utiliser les chaînes de caractères et faire une division par deux et soustraction "à la main" caractère par caractère, comme on le fait sur un papier.
Marsh Posté le 01-08-2001 à 12:37:17
Bon, j'ai une solution pour convertir directement ta chaine en chaine binaire (si,si)
En fait, je suis remonté très loin dans mes cours de math... Jusqu'en CE2, et la j'ai trouvé la réponce !
(Comme quoi, il n'y a besoin de faire Math SPE pour ça).
En fait, il faut poser la division par 2 et récupérer le reste pour créer la chaine, et recommencer avec le résultat, pour obtenir la suite !
je te donne un example après mangé, et l'algo dans la journée, si quelqu'un d'autre ne te la pas écrit d'après mes indications !
Marsh Posté le 01-08-2001 à 12:43:08
je sais bien que pour passer du decimal au binaire il faut diviser le décimal par 2, calculer le reste de la division ( modulo et ainsi de suite).
Mais comme l'a fait remarquer Carbon_14 mon nombre est trop grand pour que je puisse faire des opérations dessus!! apparement, il a une solution mais je ne l'ai pas compris...
Tu pourrais développer un peu ta stratégie Carbon_14, stp
Marsh Posté le 01-08-2001 à 12:59:41
Pour diviser un nombre contenu dans une chaîne de caractères, il fau(drai)t faire comme à la main. On prend le "premier" chiffre à gauche, on le divise par deux si > 2. Si < 2, résultat 0. Sinon, dans chaîne "résultat", on met le premier caractère obtenu. Si le reste est 1, c'est une retenue. On divise alors par deux le 0 ou 1 suivi du caractère qui suit. Le résultat va dans la chaîne. Si le "0 ou 1 suivi du caractère" est impair, retenue, etc...
Obscur, n'est-il pas ?
Peut-être qq chose comme cela pour faire une division par deux d'une chaîne
char Chaine[36]; // 35 caractères
char Resultat[36];
int iVal, iC, Retenue, Reste, Div, NbCar;
Retenue = 0;
NbCar = strlen(Chaine);
for (iC = 0; iC < NbCar; iC ++)
{
iVal = Chaine[iC] - '0'; // 0 pr "0", 9 pour "9"
iVal = 10 * Retenue + iVal;
Div = iVal / 2;
Retenue = iVal - 2 * Div;
Resultat[iC] = '0' + Div;
}
// La Retenue devrait être le 0 ou le 1 que l'on veut avoir en rang courant (poids faible de la décomposition binaire)
Marsh Posté le 01-08-2001 à 14:07:22
C'est bien ça CARBON_14.
Le fait de poser la division "à la main", comme on l'apprend en primaire et une solution au problème.
Par contre, je n'ai pas testé ta fonction, mais j'ai l'impression qu'elle ne fait pas ça...
Marsh Posté le 01-08-2001 à 14:14:50
Ce que j'ai tenté de gribouiller tout à l'heure entre deux manips concerne(rait) la division d'une chaîne de digits par deux afin d'obtenir une chaîne résultat avec émission d'un 0 ou d'un 1 (reste de la division par deux).
Il faut y faire appel le nombre de fois qu'il faut pour "épuiser" la chaîne originelle et ainsi collecter tous les 0 et les 1.
Je copie mon code et le teste ce soir at home (suis spécialiste des étourderies ). Mon boulot est prioritaire.
Marsh Posté le 01-08-2001 à 14:25:24
J'avais bien compris ça CARBON_14...
Moi aussi, mon boulot ne me permet pas de me concentrer sur le problème. De toute façon, la solution est bien la.
Il ne reste plus qu'à la rédiger "au propre".
Marsh Posté le 01-08-2001 à 15:57:43
Un coup de Google donne la division Euclidienne (je ne savais même plus à quoi elle correspondait)
http://dado59.free.fr/cours/num&cod.htm
Marsh Posté le 01-08-2001 à 18:21:56
éh bient moi, je n'arrive pas à rédiger cette méthode...Même avec tous ces indices je ne suis pas doué...
Marsh Posté le 01-08-2001 à 18:52:32
j'ai l'impression que la méthode proposée n'est réalisable que si on peut effectuer des calculs sur le nombre dont on cherche la valeur binaire...Or avec mon nombre de 35 chiffres je ne peut faire aucun calculs ( c'est d'ailleur pourquoi il est dans une chaine de caractère et non dans une variable).
Est ce que je me trompe?
Marsh Posté le 01-08-2001 à 18:52:54
Tu sais superAxel, les informations du site donne les grandes lignes, mais ne permetent pas de faire "telquel" le programme.
Si j'ai le temps ce soir, je te l'apporte demain matin !
C'est pour quel usage, sans indiscression ?
Tu dis que c'est en C++. Il faut que se soit dans une classe particulière ?
Marsh Posté le 01-08-2001 à 19:05:20
je sais bien, et je vous remercie tous de votre aide
En fait, je suis entrain de faire un stage dans une petite pme et, bien sûr, je suis pas payé!!!
Je suis sensé développer un programme en C++ (c'est la première fois que j'en fait) qui permettra (si ca marche) de traiter des infos provenant d'un banc de test. Bref, je suis un peut dans la merde!!
Je me retrouve donc avec en entrée des nombre composés d'environ 35 chiffres et il faut que je les transforme en chaine de bit pour pouvoir les traiter par la suite...
Sinon, non, pas de classe particulière.
Marsh Posté le 01-08-2001 à 19:05:32
Je comprend ton problème.
En fait, il faut que tu prennes petit bout par petit bout dans ta chaine, et non pas le nombre entier.
Quand tu poses une division à la main (123/2 par example), tu ne dis pas : "123 divisé par 2 = 61 reste 1" mais tu dis : "en 1 combien de fois 2 : zero fois, en 12 combien de fois 2 : 6 fois.
6 fois 2 12, moins 12 = 0.
Et tu descends le 3, puis tu recommences : en 3 combien de fois 2 : 1 fois. une fois 2 = 2 moins 3 reste 1.
Et tu te retrouve avec effectivement 61 et reste 1 ! (tu m'a suivi ?)
Il faut donc parcourir de gauche a droite ta chaine, prendre des "bouts" de nombre, comme si tu posais la division !
Une fois la première division finie, tu concatènes le reste (0 ou 1) dans une nouvelle chaine, et tu redivise le résultat par 2 ! Tu recommence jusqu'à ce que le résultat soit plus petit que 2, et à chaque fois, tu concatèle les restes ! C'est eux qui vont te former la chaine binaire qui représente la valeur de la chaine décimale !
Une fois arrivé à la fin, n'oubli pas de concaténé le dernier résultat (0 ou 1 donc) a la chaine, qui est en fait le dernier reste de l'opération. Voila !
Bon, ok je jetterais un oeuil !
Marsh Posté le 01-08-2001 à 19:09:53
Tu fais exprès de toujours poster 20 secondes avant moi ?
C'est sympa comme stage...
Tu sais, si ça marche, il n'y a pas de raison pour qu'ils ne soit pas reconnaissant !
Tu es en BTS ou en IUT informatique ?
Marsh Posté le 02-08-2001 à 08:52:28
J'ai testé ça hier soir, ça marchait chez moi (sur 11 digits, suffit d'adapter à plus).
NB : La calculatrice Windows permet d'afficher en décimal puis de changer en binaire, mais il y a un "bug" si le nombre est trop grand (suffit de revenir à décimal pour vérifier si des chiffres n'ont pas été perdus !!!)). Il s doivent passer par un long ou float/double, mais ça va pas.
// prototype de la fonction
int DiviseChneParDeux(char *);
// Utilisation pratique/Test
{
char Chaine[12], cTemp;
int Retour, iPos, iC;
char Bin[100];
strcpy(Chaine, "1369725233" ); //1010001101001000101100100110001
iPos = 0;
for (;
{
Retour = DiviseChneParDeux(Chaine);
if ((Retour & 2) == 2)
Bin[iPos] = '0' + 1;
else
Bin[iPos] = '0' + 0;
iPos ++;
if ((Retour & 1) == 1) break; // terminé, chaîne nulle
}
Bin[iPos] = '\0';
// Il faut ensuite retourner la chaîne tête à queue
for (iC = 0; iC < (iPos - 1) / 2; iC ++)
{
cTemp = Bin[iC];
Bin[iC] = Bin[iPos - 1 - iC];
Bin[iPos - 1 - iC] = cTemp;
}
MessageBox(hWndMain, Bin, "Bin", MB_OK);
}
// La fonction de division par deux du nombre contenu dans une chaîne de caractères szChaine et "remise" dans cette chaîne
int DiviseChneParDeux(char *szChaine)
{
int izVal, Retenue, Div, iC, Retour;
BOOL QZero;
Retenue = 0;
QZero = TRUE;
for (iC = 0; iC < strlen(szChaine); iC ++)
{
izVal = szChaine[iC] - '0'; // 0 pr "0", 9 pour "9"
izVal += 10 * Retenue;
Div = izVal / 2;
Retenue = izVal - 2 * Div;
szChaine[iC] = '0' + Div;
if (Div != 0) // chiffre autre que zéro rencontré
QZero = FALSE;
}
// La Retenue est le 0 ou le 1 que l'on a au rang courant
// Codage sur deux bits : bit 0 : 1 si fin de traitement (chaîne nulle)
// bit 1 : 0 ou 1 : reste de la division Euclidienne
Retour = 0;
if (QZero == TRUE) Retour += 1;
if (Retenue == 1) Retour += 2;
return Retour;
}
A améliorer par les pros. C'est du code d'amateur
Marsh Posté le 02-08-2001 à 09:03:51
Je te remercie, cé vraiment sympa...
C'est pas moi qui vais améliorer le code, je suis loin d'être un pro comme vous avez pu vous en douter...
Marsh Posté le 02-08-2001 à 09:19:52
Reste à trouver un matheux (mes souvenirs ont plus de 25 ans) pour déterminer quel est le nombre de caractères dans la chaîne destinatrice par rapport au nombre de digits de la chaîne d'origine.
Suffirait d'essayer avec une chaîne à 37 caractères pour avoir une valeur limite. J'ai mis 100 "au pif".
Marsh Posté le 02-08-2001 à 09:36:10
Bon travail CARBON_14 ! Moi, je n'ai pas eu le temps de finir ça hier soir... J'ai fait un peut différement, mais le résultat devrait être le même. (je le finirai par fierté )
Marsh Posté le 02-08-2001 à 09:52:08
Ca m'intéressera, car on a chacun des réflexes et les miens ne sont pas toujours "optimisés".
A poster dès que c'est terminé !
Etonnant un appareil/système qui sort des résultats dans un nombre de 36 chiffres... Si c'était 36 états codés sur un caractère, cela rejoindrait mon égarement du début...
Une fois terminé, on va lancer un concours pour multiplier deux nombres de 36 chiffres stockés dans deux chaînes de caractères.... Voire juste l'addition pour s'échauffer.
Marsh Posté le 02-08-2001 à 10:01:59
OK, si j'ai le temps, j'essai de finir ça ce soir ! (ha, le temps...)
Effectivement, c'est étrange comme système...
Moi j'espère qu'au final, il ne falait pas coder chaque caractère , comme tu le pensais au début !
Pour le concours, je suis partant, mais c'est toujours un problème de temps... Mais une fois que l'on aura fait tous les opérateurs, on poura toujours créer petite lib de calcul sur les grand nombres
Marsh Posté le 02-08-2001 à 10:47:03
Ainsi, nous pourrons calculer la distance Terre-Soleil en microns connaissant la distance terre-Lune et Lune-Soleil .
On s'y mettra quand quelqu'un en aura besoin...
Marsh Posté le 02-08-2001 à 10:57:23
Ne vous inquietez pas, il ne fallait pas coder chaque caractère. Vos effort, que j'apprécie , n'ont pas été inutiles, encore merci!
Marsh Posté le 02-08-2001 à 13:30:09
Hier j'avais fait ce qui est ci-dessous, mais CARBON_14 m'a bien devancé.
Je poste quand même ce petit programme pour donner une autre solution qui dans la base est la même que celle de CARBON_14.
En commentaire il y a la formule qui donne le nombre de chiffres de la chaine résultante.
Il peut très facilement être adaptée pour généraliser la conversion d'une base de départ vers une base d'arrivée.
Attention, les tableaux ont le chiffre le moins significatif en 0, l'initialisation du style tab[10]="1234" ne fait pas cela, mais le contraire !!!
A+
----------------------------------
#define NBDEC 36 /* nombre de chiffres à convertir */
#define NBBIN 120 /* nombre de chiffres du résultat = INT( LOG(10^NBDEC)/LOG(2) ) + 1 */
main()
{
char TableDec[NBDEC+1];
char TableBin[NBBIN+1];
int i,j,reste,temp;
/* Initialisation de TableDec en ASCII avec le chiffre le moins significatif en 0 */
/* Après la conversion, le contenu de ce tableau sera perdu */
/* transformation ASCII en décimal */
for (i=0;i<NBDEC;i++)
TableDec[i]-='0';
/* chiffre binaire du moins significatif au plus significatif */
for (j=0;j<NBBIN;j++)
{
reste=0;
/* on fait la division par 2 du grand nombre décimal avec retenue */
/* chiffre décimal du plus significatif au moins significatif */
for (i=NBDEC-1;i>=0;i--)
{
temp=reste * 10 + TableDec[i]; /* 10 pour la base de départ */
TableDec[i]=temp / 2; /* 2 sur les 2 lignes */
reste=temp % 2; /* pour la base d'arrivée */
}
TableBin[j]=reste+'0';
}
/* Utiliser résultat dans TableBin en ASCII avec le bit le moins significatif en 0 */
}
[edtdd]--Message édité par tfj57--[/edtdd]
Marsh Posté le 31-07-2001 à 20:53:01
salut,
j'ai un problème concret...J'ai un nombre à 36 chiffres représentés par une chaîne de caractères (char Table[36]) et je souhaite convertir ce nombre en bits, c'est à dire d'obtenir une chaine de bits représentant la valeur de mon nombre.
Quelqu'un aurait il une idée? Merci d'avance