| |||||
| Dernière réponse | |
|---|---|
| Sujet : Passer d'une chaine de chiffre à une chaine de bit??? | |
| HelloWorld | j'apporte une petite pierre a l'edifice ...
si tu as l'intension de manipuler ces nombres (addition, multiplication, ...) il serait petetre bon de lire cet article koikilensoit, c'est tout de meme une bonne doc informative : http://www.citeweb.net/discase/9/GDNOMBRE.htm les exemples donnés manipulent des tableaux de chiffres ... c'est donc tres proche de ton cas (au lieu de stocker ton nombre de caractere, tu le stocke dans un tableau de chiffres) |
| Aperçu |
|---|
| Vue Rapide de la discussion |
|---|
| HelloWorld | j'apporte une petite pierre a l'edifice ...
si tu as l'intension de manipuler ces nombres (addition, multiplication, ...) il serait petetre bon de lire cet article koikilensoit, c'est tout de meme une bonne doc informative : http://www.citeweb.net/discase/9/GDNOMBRE.htm les exemples donnés manipulent des tableaux de chiffres ... c'est donc tres proche de ton cas (au lieu de stocker ton nombre de caractere, tu le stocke dans un tableau de chiffres) |
| TotOOntHeMooN | Pour le soft, essai avec PowerPoint... |
| TotOOntHeMooN | OK, bon scan, bon weekend et a lundi. Avec une solution... |
| Carbon_14 | Voui. Plein de chimie et de l'info le soir/WE/partie des vacances (l'info est un outil utilitaire pour moi). Mes collègues sont restés à QB4.5, voire Mathematica/Mapple/ et je sais pas quoi.
Quand on est pas pro, c'est fou ce qu'on perd de temps à réinventer la Win_roue, surtout en C. Le Pingouin_roue, ça promet aussi... Faut que je finisse scannages de diapos d'un mariage d'un collègue le week-end dernier, fabrication du CD, trouver/écrire soft(?) pour faire diaporama, .. donc pas de temps pour le sujet. :( :) Super algo ultra rapide multibase lundi matin sur des chaînes de longueur quelconque :??: ... |
| TotOOntHeMooN | Oui, mais se sera pour ce weekend, car j'ai pas envie de partir trop tard du travail, pour une fois...
D'ailleur, tu fais quoi comme job CARBON_14 ? Dans la recherche scientifique je supose ? |
| Carbon_14 | Un problème en VB(3) est la lenteur d'accès des fonctions de maipulation de chaînes. En VBA, c'est peut-être mieux.
Le traitement d'une chaîne de 1024 caractères issue d'un oscillo (de grande marque :)) demandait 1 seconde pour transformer les 1024 char en 1024 int via la fonction mid$() (PC à 33MHz). J'avais écrit une DLL en (B)C pour utiliser avec VB(3), ca prenait 1,1 milli seconde :D!! En C, un char <=> int direct => très rapide. On va y arriver ! :hello: |
| TotOOntHeMooN | Tu fais confiance à la calculatrice windows CARBON_14 ? :crazy: Bon, ça se tente, non ? |
| TotOOntHeMooN | Merci pour ta solution nur.
Je jette un oeuil sur l'algo que tu utilises... A première vue, ça doit pas être bien rapide, mais je me trompe peut-être. Tu ne peux pas nous pondre la même chose en C/C++ ? |
| Carbon_14 | TotOOntHeMooN La calculatrice Windows donne 0100 1101 0010 Bin pour 1234 Décimal ou 4D2 Hexa. C'est donc tout bon. :jap: |
| nur | Une version sur Excel sans limitation de bits:
Dim bi(126) 'ou plus Sub rr() chainechiffre = "1234567890123456789012345678901234567" lg = Len(chainechiffre) - 1 cc = Len(chainechiffre) - 1 i = O While cc > 0 i = i + 1 compty = compty + Mid(chainechiffre, i, 1) * 10 ^ cc cc = cc - 1 Wend compty = compty + Mid(chainechiffre, lg + 1, 1) dd = 4 * lg - 2 While (chainechiffre / 2 ^ dd) < 1 dd = dd - 1 Wend i = dd cpt = 1 reste = chainechiffre - 2 ^ (i) bi(cpt) = i i = i - 1 Do Do divis = reste / 2 ^ i If (divis < 1) Then i = i - 1 Loop While divis < 1 cpt = cpt + 1 bi(cpt) = i reste = reste - 2 ^ i i = i - 1 Loop While reste > 1 If Mid(chainechiffre, lg + 1, 1) Mod 2 > 0 Then cpt = cpt + 1 bi(cpt) = 0 End If For i = 1 To cpt Sheets("feuil1" ).Range("a1" ).Offset(i - 1).Value = bi(i) Next retrans (cpt) End Sub Sub retrans(ch) 'ch=cpt chainet = "" For i = 1 To ch If bi(i) >= 0 Then chainet = chainet & "1" diff = bi(i) - bi(i + 1) - 1 If diff > O Then For j = 1 To diff chainet = chainet & "0" Next End If Next MsgBox (chainet) Sheets("feuil1" ).Range("C41" ).Value = chainet & "B" End Sub |
| TotOOntHeMooN | Ca marche sur papier, alors il n'y a pas de raison...
Par example, pour diviser 1234 par 2, tu vas essayer 1(0x), puis 12(6x), puis 3(1x), puis 14(7x) il te reste 0 et ton resultat est 617, et tu recommence. si tu divises 1234 toujours par 2, mais en prenant des tranches de 2, tu vas essayer 12(6x), puis 34(17x), il te reste 0, et ton resultat est 617, mais tu n'a fait que deux divisions au lieu de 4 ! Maintenant, tu peux augmenter la taille des tranche (8max, pour un entier). Ainsi, 1234 poura donner le resultat 617 reste 0 en une seule fois, et ceux pour tous nombre contennu dans une tranche. Biensur, le resultat est toujours binaire ;) dans notre cas. Si maintenant, on fait les division par 16, avec des tranches de 8, on aura le calcul suivant: 1234/16 (77x ou plutot 4Dx) reste 2 et onfait la "conversion" hexa -> binaire, comme je l'ai expliqué il y a quelques jours. 4: 0100 D: 1101 2: 0010 donc 1234 = 0100 1101 0010 |
| Carbon_14 | Ca serait quand même intéressant (j'utilise ma montre sur mon 486/100 en faisant des boucles répétitives ( :( )) de vérifier si on va 64 fois plus vite en coupant en tranches et en divisant par 16..
Je me demandais juste si on peut diviser par 16 une chaîne découpée en tronçons. Ne faut-il pas diviser la chaine d'un seul bloc et reposer l'opération comme on l'a fait (dans une autre base) selon TotOOntHeMooN Posté le 03-08-2001 à 09:12:07. Casse-tête du vendredi. :D . Restons binaires.. |
| TotOOntHeMooN | Si quelqu'un à un Linux sous la main, il execute la commande time suivi du nom de son programme comme argument.
Pas besoin de se prendre la tête a écrire une routine ! |
| Carbon_14 | Comme quoi, quand tout le monde a des idées, on peut arriver à "booster" les algorithmes. On part de la base, et les suggestions aident à pulvériser le temps de calcul. Un courageux pour lancer des tests et mesurer le gain ? :??: |
| TotOOntHeMooN | En se moment, on se pose plus des questions d'optimisation de de calcul ;) Mais c'est vrai, que diviser par 16 et convertir chaque octet en sa valeur binaire, et bien plus efficace. Depuis le debut, toules les methodes proposées repose sur le meme principe, qui est de prendre caractere par caractere dans la chaine de depart, et effectuer les divisions. On peut très bien prendre par tranche de 8 caracteres, convertir le bout de chaine en entier, et effectuer la division. (encore 8 fois plus vite. Si on cumule les deux methodes, on va 64x plus vite ! |
| Carbon_14 | :D A tester sur des nombres de 35 chiffres.
L'utilisateur va pouvoir choisir (il a toutes les données pour tester lui-même). Dans mon exemple de l'autre jour, on peut aussi laisser tomber les zéros de poids fort au fur et à mesure qu'on fait les divisions. Ca économise pas mal de temps :lol: . |
| Mara's dad | Une idée pour aller plus vite.
Au lieu de faire les divisions par 2, pour obtenir le nombre en binaire, ne serait-il pas plus rapide de faire une conversion en hexa ( divisions par 16 ) donc 8 fois moins de divisions. Ensuite, la conversion de hexa vers binaire est triviale. |
| Carbon_14 | Cela n'empêche qu'il faut des fois NE PAS OUBLIER d'ajouter 0,5 quand on fait des divisions car en float, on a des fois des surprises (127,99999 / 128,0000 ne donne pas 1).
:D |
| TotOOntHeMooN | Bon, la prochaine fois je réfléchirais avant de dire une connerie... Il faut bien mettre 1, pour etre sur du resultat. |
| TotOOntHeMooN | Dans la série je discute tout seul, je voudrait apporter une petite modification sur la formule donnée par tfj57.
a la fin, il ne faut pas ajouter 1, mais 0.5 En effet, si la division entre les deux reel, donne un resultat "juste", genre 128.00000000 (ca arrive souvant) et que l'on ajoute 1, alors la taille de la chaine allouée après conversion en nombre entier (tronquage) sera de 129 et non pas 128. Le fait d'ajouter 0.5, permet d'avoir un résultat à l'unitée supérieure, seulement si nécessaire. |
| TotOOntHeMooN | Si ça intéresse quelqu'un, j'ai fait une variante, qui permet de convertir des grands nombres entiers entre n'importe quelle base.
(200 max) |
| TotOOntHeMooN | Bon, comme j'ai vu qu'une autre personne avait posté une réponce, j'ai pris un p'tit moment sur mon travail, pour finir ma version.
Je me suis permis de prendre la formule que tjf57 a mis en commentaire, car la "mienne" (fait maison) devenait trop aproximative, quand la chaine donnée grandissait. Cette version n'a pas de limite en taille. ------------------------------------------------------------- #include <stdio.h> #include <string.h> #include <math.h> // macros de conversion ASCII <-> chiffre #define ATOC(a) ((a)-0x30) #define CTOA(c) ((c)+0x30) // retourne une chaine binaine, valeur de la // chaine decimale passee en paramettre const char * dec2bin(const char *dec) { char *binString, *decString; int binSize, decSize; int binPos, decPos; int valeur, reste; // initialisation decSize = strlen(dec); binSize = (int)(log(pow(10, decSize))/log(2) + 1); // allocation memoire decString = new char[decSize+1]; binString = new char[binSize+1]; // copie de la chaine a traiter strcpy(decString, dec); for (binPos=binSize-1 ; binPos>=0 ; binPos--) { reste = 0; for (decPos=0 ; decPos<decSize ; decPos++) { valeur = ATOC(decString[decPos]) + reste*10; reste = valeur % 2; decString[decPos] = CTOA(valeur>>1); } // ecriture de la chaine binaire binString[binPos] = CTOA(reste); } // fin de la chaine binaire binString[binSize] = '\0'; // libere la memoire prise par decString delete []decString; // retourne l'adresse de la chaine binaire return (binString); } // Essai int main() { const char dec[] = "12345678901234567890123456789012345"; const char *bin = dec2bin(dec); printf ("%s\n", bin); // si plus besoin de bin, il faut liberer la memoire delete [](void*)bin; return 0; } ------------------------------------------------------- Mon idée de départ était de faire les divisions sur 8 chiffres à la fois, mais cette version de base va déjà très bien. Et tout le monde a déjà posté la sienne, alors ... |
| tfj57 | 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] |




