Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

STRING -> BINAIRE (LONGUEUR PSEUDO INFINIE)


Information sur la source

Catégorie :Delphi et asm Niveau : Débutant Date de création : 30/09/2004 Date de mise à jour : 02/10/2004 21:21:18 Vu / téléchargé: 6 645 / 142

Note :
10 / 10 - par 1 personne
10,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

Commentaire sur cette source (28)
Ajouter un commentaire et/ou une note

Description

Cliquez pour voir la capture en taille normale
voilà, comme vous savez en C il y a les fonctions atoi et itoa pour convertir une chaîne en int (entier) qui en fait n'est qu'un nombre binaire sur 4 octets et vice versa. Ce que je vous propose ici c'est une fonction (en fait y'en faut plusieurs, c'est pas aussi simple ;-)) qui permet de calculer le nombre binaire à partir d'une string, quelle que soit sa longueur...

regardez le screenshot pour un petit exemple ;-)

Now on s'interesse au code:
 

Source

  • unit cpute;
  • interface
  • type
  • TNumber = record
  • buf: Pointer;
  • len: Cardinal;
  • end;
  • function StrToBin(var n: TNumber): Cardinal;
  • function BinToStr(var n: TNumber): Cardinal;
  • implementation
  • const
  • _0000000ah: Cardinal = $a;
  • // ******************************************************************
  • // ******************************************************************
  • // * Part 1:
  • // * ~~~~~~~
  • // *
  • // * the coming functions do only convert numbers (base 10 (<)-> base 2)
  • // ******************************************************************
  • // ******************************************************************
  • // ******************************************************************
  • // * convert from ASCII digit to binary digit
  • // * and check that the buffer doesn't contain any invalid digit
  • // * Result = 0: ok; Result <> 0: position of the invalid digit in v_eax (buf)
  • // * (where 1 is the first position)
  • // ******************************************************************
  • function ChrToBin(v_eax: Pointer; v_edx: Cardinal): Cardinal;
  • asm
  • xor ecx,ecx
  • @loop:
  • cmp ecx,edx
  • je @end
  • sub byte ptr [eax+ecx],30h
  • jc @exit
  • cmp byte ptr [eax+ecx],9
  • ja @exit
  • inc ecx
  • jmp @loop
  • @end:
  • or ecx,0ffffffffh
  • @exit:
  • inc ecx
  • mov eax,ecx
  • end;
  • // ******************************************************************
  • // * convert from binary digit to ASCII digit
  • // ******************************************************************
  • procedure BinToChr(v_eax: Pointer; v_edx: Cardinal);
  • asm
  • xor ecx,ecx
  • @loop:
  • cmp ecx,edx
  • je @end
  • add byte ptr [eax+ecx],30h
  • inc ecx
  • jmp @loop
  • @end:
  • end;
  • // ******************************************************************
  • // * compute a binary number from a string (previously substracted by $30)
  • // * result is the length of the binary number (unit: 32 bit)
  • // ******************************************************************
  • function CputeBin(v_eax: Pointer; v_edx: Cardinal): Cardinal;
  • asm
  • push ebx
  • push ebp
  • push esi
  • push edi // regs we will use
  • mov ebp,eax // v_eax (buf) is now ebp
  • mov ebx,ebp // ebx is another pointer for buf, but it will be modified
  • mov esi,edx // v_edx (len) is now esi
  • xor edi,edi // edi will be the size of the binary number (in DWORD)
  • @loop:
  • cmp esi,0 // is it the end of the buffer?
  • je @end // yes? let's go to the end
  • cmp byte ptr [ebx],0 // is the current byte 0?
  • jne @begin // no? then we can compute binary (000023, '0000' is obsolet)
  • // obsolet zeros will be used to store the result
  • inc ebx // yes? inc and dec pointers
  • dec esi
  • jmp @loop // ... and check next byte
  • @begin: // let's convert to binary!
  • xor ecx,ecx
  • xor eax,eax
  • xor edx,edx
  • @loop2:
  • mul _0000000ah // remainder * 10
  • push edx // edx is the current numerator
  • mov dl,byte ptr [ebx+ecx] // current digit
  • add eax,edx // add decimal digits, eax becomes the new numerator
  • pop edx
  • jnc @nc // well, only a matter of addition remainder
  • inc dl
  • @nc:
  • mov byte ptr [ebx+ecx],dl // new digit, dl represents the current
  • // quotient given by a division by 2^32
  • inc ecx
  • cmp ecx,esi
  • jb @loop2 // loop to treat the whole string
  • // eax is the last remainder of a divsion by 2^32
  • mov dword ptr [ebp+edi*4],eax // save our binary number 32 bits by 32 bits
  • inc edi // adjust pointers...
  • add ebx,4
  • sub esi,4
  • jnc @loop // let's offer ourselves a new division by 2^32 ;-)
  • // till string number is greater than 2^32
  • @end:
  • mov eax,edi // eax is Result
  • pop edi
  • pop esi
  • pop ebp
  • pop ebx
  • end;
  • procedure CputeStr();
  • asm
  • end;
  • procedure ReverBin(v_eax: Pointer; v_edx: Cardinal);
  • asm
  • dec edx
  • xor ecx,ecx
  • @loop:
  • cmp ecx,edx
  • jae @end
  • push dword ptr [eax+ecx*4]
  • push dword ptr [eax+edx*4]
  • pop dword ptr [eax+ecx*4]
  • pop dword ptr [eax+edx*4]
  • inc ecx
  • dec edx
  • jmp @loop
  • @end:
  • end;
  • procedure CpyStr();
  • asm
  • end;
  • function StrToBin(var n: TNumber): Cardinal;
  • begin
  • // convert ASCII digit to binary digit and checks there is no invalid digit
  • Result := ChrToBin(n.buf, n.len);
  • if (Result <> 0) then Exit;
  • // compute the binary number from input (and its length, 32 bits as unit)
  • n.len := CputeBin(n.buf, n.len);
  • if (n.len = 0) then Exit;
  • // bytes are reversed
  • ReverBin(n.buf, n.len);
  • end;
  • function BinToStr(var n: TNumber): Cardinal;
  • begin
  • end;
  • // ******************************************************************
  • // ******************************************************************
  • // * Part 2:
  • // * ~~~~~~~
  • // *
  • // * the coming functions do all the operations (+, -, *, /, gcd)
  • // ******************************************************************
  • // ******************************************************************
  • // I am too busy with my studies...
  • end.
unit cpute;

interface
                     
type
  TNumber = record
    buf: Pointer;
    len: Cardinal;
  end;

function StrToBin(var n: TNumber): Cardinal;
function BinToStr(var n: TNumber): Cardinal;

implementation

const
  _0000000ah: Cardinal = $a;

// ******************************************************************
// ******************************************************************
// * Part 1:
// * ~~~~~~~
// *
// * the coming functions do only convert numbers (base 10 (<)-> base 2)
// ******************************************************************
// ******************************************************************

// ******************************************************************
// * convert from ASCII digit to binary digit
// * and check that the buffer doesn't contain any invalid digit
// * Result = 0: ok; Result <> 0: position of the invalid digit in v_eax (buf)
// * (where 1 is the first position)
// ******************************************************************
function ChrToBin(v_eax: Pointer; v_edx: Cardinal): Cardinal;
asm
  xor ecx,ecx
    @loop:
    cmp ecx,edx
    je @end
    sub byte ptr [eax+ecx],30h
    jc @exit
    cmp byte ptr [eax+ecx],9
    ja @exit
    inc ecx
    jmp @loop
    @end:
  or ecx,0ffffffffh
  @exit:
  inc ecx
  mov eax,ecx
end;

// ******************************************************************
// * convert from binary digit to ASCII digit
// ******************************************************************
procedure BinToChr(v_eax: Pointer; v_edx: Cardinal);
asm
  xor ecx,ecx
    @loop:
    cmp ecx,edx
    je @end
    add byte ptr [eax+ecx],30h
    inc ecx
    jmp @loop
    @end:
end;

// ******************************************************************
// * compute a binary number from a string (previously substracted by $30)
// * result is the length of the binary number (unit: 32 bit)
// ******************************************************************
function CputeBin(v_eax: Pointer; v_edx: Cardinal): Cardinal;
asm
  push ebx
  push ebp
  push esi
  push edi  // regs we will use 

  mov ebp,eax  // v_eax (buf) is now ebp
  mov ebx,ebp  // ebx is another pointer for buf, but it will be modified
  mov esi,edx  // v_edx (len) is now esi
  xor edi,edi  // edi will be the size of the binary number (in DWORD)

    @loop:
    cmp esi,0  // is it the end of the buffer?
    je @end  // yes? let's go to the end
    cmp byte ptr [ebx],0  // is the current byte 0?
    jne @begin  // no? then we can compute binary (000023, '0000' is obsolet)
                // obsolet zeros will be used to store the result
    inc ebx  // yes? inc and dec pointers
    dec esi
    jmp @loop  // ... and check next byte

    @begin:  // let's convert to binary!
    xor ecx,ecx
    xor eax,eax
    xor edx,edx

      @loop2:
      mul _0000000ah  // remainder * 10
      push edx  // edx is the current numerator
      mov dl,byte ptr [ebx+ecx]  // current digit
      add eax,edx  // add decimal digits, eax becomes the new numerator
      pop edx
      jnc @nc  // well, only a matter of addition remainder
      inc dl
      @nc:
      mov byte ptr [ebx+ecx],dl  // new digit, dl represents the current
                                 // quotient given by a division by 2^32
      inc ecx
      cmp ecx,esi
      jb @loop2  // loop to treat the whole string
      
    // eax is the last remainder of a divsion by 2^32
    mov dword ptr [ebp+edi*4],eax  // save our binary number 32 bits by 32 bits
    inc edi  // adjust pointers...
    add ebx,4
    sub esi,4
    jnc @loop  // let's offer ourselves a new division by 2^32 ;-)
               // till string number is greater than 2^32
    @end:

  mov eax,edi  // eax is Result
  
  pop edi
  pop esi
  pop ebp
  pop ebx
end;

procedure CputeStr();
asm
end;

procedure ReverBin(v_eax: Pointer; v_edx: Cardinal);
asm
  dec edx
  xor ecx,ecx
    @loop:
    cmp ecx,edx
    jae @end
    push dword ptr [eax+ecx*4]
    push dword ptr [eax+edx*4]
    pop dword ptr [eax+ecx*4]
    pop dword ptr [eax+edx*4]
    inc ecx
    dec edx
    jmp @loop
    @end:
end;

procedure CpyStr();
asm
end;

function StrToBin(var n: TNumber): Cardinal;
begin
  // convert ASCII digit to binary digit and checks there is no invalid digit
  Result := ChrToBin(n.buf, n.len);
  if (Result <> 0) then Exit;
  // compute the binary number from input (and its length, 32 bits as unit)
  n.len := CputeBin(n.buf, n.len);
  if (n.len = 0) then Exit;
  // bytes are reversed
  ReverBin(n.buf, n.len);
end;

function BinToStr(var n: TNumber): Cardinal;
begin
end;

// ******************************************************************
// ******************************************************************
// * Part 2:
// * ~~~~~~~
// *
// * the coming functions do all the operations (+, -, *, /, gcd)
// ******************************************************************
// ******************************************************************

// I am too busy with my studies...

end.

Conclusion

tout de suite vous avez remarquez deux choses: c'est du pur assembleur, et deuxio oui c'est de l'assembleur inline sous delphi (ce qui explique la première affirmation). Bon, je ne pense pas qu'il soit difficile d'adapter ce code pour qu'il compile sous un pur compilo assembleur comme tasm, mais je ne connais pas assez l'assembleur pour ça, je sais que écrire des algos (et encore ;-)).

donc comment ça marche tout ce binz? première étape, on effectue une soustraction de 0x30 sur tous les octets de la string, ainsi on peut accéder directement aux chiffres (en binaire donc) de la string. Ensuite on effectue une succession de divisions par 2^32 jusqu'à ce que le reste soit inférieur à 2^32. Le résultat de la division est foutu dans la string, un chiffre par octet.  Le dernier reste d'une division par 2^32 de la string constitue 32 bits de notre futur nombre en binaire... ouais c'est complexe, et c'est pas en trois lignes que je peux donner le détail. Pour bien comprendre faut vraiment étudier la source à fond.

le buffer (en fait TNumber) donné à la fonction contient le nombre binaire une fois la fonction executée, SANS AUTRE ALLOCATION DE MEMOIRE (elle est pas belle la vie?). Donc il faut faire une copie de votre string avant si vous en avez besoin plus loin...

Le blem c'est que j'ai pas le temps de faire la fonction dans l'autre sens, à savoir convertir un nombre binaire énorme en string... Après, ce serait interessant de programmer les opérations de base comme l'addition la soustraction la multiplication et la division, en traitant le nombre 32 bits par 32 bits, le plus rapidement possible. Après on peut encore combiner tout ça à un parseur et essayer de lui faire supporter des nombres réels etc. Bref, on s'reprogramme un p'tit maple9? lol.

voilà, c'est complexe, mais si vous voulez essayer: foutez un très grand nombre en décimal dans le fichier 'in' puis tapez: int -b out in
et c'est parti, regardez le résultat dans le fichier 'out' (les packs de 4 octets sont en little endian)

Ptet un jour j'aurai le temps de continuer cette source mais pour l'instant c'est pas possible (grandes vacances?), donc si ça interesse quelqu'un en attendant je peux toujours l'aider un peu, et pis sinon ben bonne soirée quand même ;-)

Twis++;
 

Fichier Zip

Pour les "Membres Club", vous pouvez télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip

Historique

02 octobre 2004 21:21:18 :
- nombre binaire (résultat) placé directement dans le buffer donné (en entrée) à la fonction StrToBin -> pas d'autre allocation de mémoire. - nombre binaire (résultat) par paquets de 32 bits en little endian.

Commentaires et avis

signaler à un administrateur
Commentaire de Bombela le 01/10/2004 15:05:27

Pour continuer le message que tu m'as envoier, j'ai une petite remarque...

Tu sort ton binaire en... big endian !

Alors que sur les pc à base d'intel (Sur quoi tu fais mumuze avec Delphi ;) sont en little endian !

Faudrait faire une petite update là ;)

@+

signaler à un administrateur
Commentaire de Bombela le 01/10/2004 15:09:34

Tien j'n poste encore un de message ! lol

Je pense qu'au final, un calcul sur des chifre décimaux serais quand même plus rapide !

Parce qu'il n'y aurais par de perte de temps de convertion de nombre décimal en binaire !

De plus, tas fonctions passe par un buffer temporaire, et si ton nombre fais 3 go de long, et bien sur un Iintel 32, t'es fini...

@+

signaler à un administrateur
Commentaire de TheWhiteShadow le 01/10/2004 17:15:41

bon alors primo j'ai rien capté au premier message, je vois pas du tout ce que tu veux dire avec big ou little endian alors détaille ;-).

et deuxio, je ne passe pas par un buffer temporaire: le résultat est foutue au fur et à mesur dans la string (mais à l'envers) donc la derniere etape consiste à copier les octets dans le dernier buffer dans le bon ordre. Ptet qu'on peut le faire direct dans le bon sens mais se serait un peu plus complexe... sinon tu peux tjrs passer par un fichier (ok ok pas la meilleure soluce) mais bon ça régle le prb de mémoire si tu veux et retourner des octets c'est pas le truc le plus long/dur à faire pour un pc... si? lol. Aussi, le nombre en pure binaire est bien moins long qu'en string...

et trisio (ou je sais plus comment on dit), si tu n'es pas convaincu qu'un calcul en assembleur par paquets de 32 bits est plus rapide qu'une string alors là je sais pas ce qui faut faire... d'autant que si tu veux faire un algo avec des longues boucles (genre calcul si un nombre est premier), tu crois pas que le mieux est l'assembleur plutôt qu'une pauvre string? Mais même pour des caluculs simples... je t'accorde un point: sûrement que pour des chaînes pas trop longues les string sont plus rapides (aucune idée d'estimation), mais pour des nombres d'une longueur vraiment considérable, pas l'ombre d'un doute que le 32 bits est (bcp) plus rapide.

Merci pour tes commentaires, mais détaille certains points.

++Twis;

signaler à un administrateur
Commentaire de Bombela le 02/10/2004 16:25:15

Bon, je vais t'expliquer :

Alors, pour le Big Endian, les octets sont codé à l'endroit.
C'est à dire que :

0xF5             > 0xF5
0xF5AB         > 0xF5AB
0xF5ABCD10 > 0xF5ABCD10

C'est le principe des processeurs Motorola. (Si tu sais ce que c'est, moi pas ;)

Les PC sur la base d'Intel fonctionnent en Little Endian,
et donc les octets sont inversé :

0xF5             > 0xF5
0xF5AB         > 0xABF5
0xF5ABCD10 > 0x10CDABF5

Alors un moyen simple pour ne pas faire l'invertion soit même, c'est de mettre les octets dans un registre 32 bits, puis de le mettre dans un petit buffer de 32 bits et  l'envoyer dans le fichier !
C'est le CPU qui feras la convertion pour la mémoire en little endian.

Pour ce qui est des calculs en 32 bits, t'as tout à fais raison !

Je t'avoue, honteusement, avoir lu tas source en diagonale... J'atais pressé (escuse minable) ...
Je n'avais pas vu que tu fesais l'invertion dans la string elle même, sans un autre buffer !

Ensuite, sache que pour moi, une string, c'est une suite d'octets, terminé par un 0.
Donc, pas le type string de delphi !

De plus, je me demande vraiment quelle est la courbe de gain de vitesse entre les string décimale (les opérations comme à l'école ;) et les string binaire (les opération en 32 bits).

Faudrais faire un calcul de vitesse...
Si tu veux bien coder le myen de faire une addition, et calculer le temps qu'il faut pour décoder, additionner, et recoder (Vu que tu l'as pas codé le recodage ;0), il suffit de multiplier par 2 le  le temps de décodage).

Si tu veux bien faire ça, je code une addition en décimale.

Ensuite, on feras un truc du style multiplication, ce qui consisterais pour moi en plein d'addition, et pour toi en multiplication du proc.

Ca nous permettra de trouver l'équilibre entre les deux méthode... très utile pour le future !

@+

signaler à un administrateur
Commentaire de TheWhiteShadow le 02/10/2004 21:48:20

donc voilà, ptite mis a jour: juré que le prog n'utilise pas plus que la mémoire de la string (résultat donné dans le buffer d'entré, la string), et deusio en little endian comme tu m'avais demandé en fait t'as raison c débile de retourner par octet, pcq il aurait fallu les re-retourner pour faire les opérations (addition etc...). m'enfin vérifie quand même que c ok (que c bien en little endian).

maintenant, l'addition (le truc le plus facile, franchement je pense pas avoir de mal à le coder), je fais comment? deux buffers qui en donnent un troisième? ou deux buffers qui donnent deux buffers? (la première soluce me plaît mieux...) enfin tu vois faut réfléchir à ce genre de question avant de se lancer.

mais le pire, c'est pour le bin->str. en effet il est possible de foutre le nombre binaire dans la string pcq le nombre binaire est bcp plus petit. mais l'inverse... 2^32-1 = 4 milliards, 9 chiffres, ça rentre mal dans 4 octets... encore on pourrait faire deux chiffres par octet et on est que à la possibilité de mettre 8 chiffres. bref on l'a dans le c*l si tu vois ce que je veux dire. je serai donc obligé de passer par un autre buffer et ça va pas être du gateau, pcq je ne connais pas à priori la taille que fera la string... en str->bin c t moins complexe pcq tout est plus petit quand tu passes à binaire. pour conclure ça va pas se faire aussi simplement que ça, faut que j'y réfléchisse pendant un bon moment... bien sûr toute proposition est la bienvenue ;-)

mais j'en suis pas encore venu au problème majeur: jai pas de temps!!!!!!!!!!! ouain... et ouais c'est la vie, demain je dois faire une p*tain de dissert de philo et en plus je bosse pour les TPE sur un mot 3d en C, alors les nombres en binaire... mais comme ça m'interesse à fond et que t'es partant pour faire un truc pour comparer et tout et tout, je vais appliquer ma phrase de toujours: si tu n'as pas le temps, donne toi le temps. d'autant que je devrais avoir plus d'heures de dispo à partir de WE prochain... ça va, elle t'interesse ma vie? lol

Twis++;

"Ensuite, sache que pour moi, une string, c'est une suite d'octets, terminé par un 0.
Donc, pas le type string de delphi !"
> ben heureusement, là c'est l'appelation que je lui donne qui est abusive, en fait c'est un buffer de bytes dont la taille est contrôlée par une constante.

signaler à un administrateur
Commentaire de Bombela le 03/10/2004 19:35:56

Ah ah ! Alors puisque tu est partant, moi aussi !

Vu que le but est d'avoir la plus grande vitesse,  et le plus grand nombre possible, optimize au maximum !
Mais faut pas non plus que ça soit bloqué !

Alors, pour partir avec des chance égale, je vais faire comme toi, un prog Delphi, qui prend un fichier et ressort dans un autre et optimisé en assembleur.

Voilà !

Et vraiment merci de jouer le jeux !

Et t'inquiète pour le temps libre, j'attendrais ;0)

@+

signaler à un administrateur
Commentaire de TheWhiteShadow le 14/10/2004 16:56:56

pas le temps de coder, mais je note les quelques points qu'il faudra traiter (pour pas les oublier ;-)):

- Virer la fonction ReverBin(). Ainsi, tous les dword seront en little endian, eux-même "à l'envers" dans le buffer. Il suffirait donc d'inverser l'ordre des octets pour avoir le nombre entier en binaire dans "l'ordre". Mais on ne perd pas de temps à inverser quoi que ce soit, tout reste retourné en mémoire. Il faudra donc en tenir compte pour les opérations.

- Améliorer les boucles de la source. Pour l'instant elles se présentent comme suit:
  xor ecx,ecx
    @loop:
    cmp ecx,value_max
    je @end
    [...]
    inc ecx
    jmp @loop
  @end:
Il serait préférable de les transformer en:
  xor ecx,ecx
    @loop:
    [...]
    inc ecx
    cmp ecx,value_max
    je @loop
Comme on peut voir, le code est un peu moins long, du fait qu'il y a un jmp en moins dans le code. Cette modification peut sembler peu significative quant au temps mis par le processeur pour traiter la boucle, mais notre but et de faire une source entièrement fonctionnelle et la plus rapide possible, donc le gain peut être senti si on applique ce changement à toutes les boucles du programme (sachant qu'il y en a qui sont très très longues à exécuter suivant la taille des nombres mis en jeu).
Mais attention, il faudra traiter le cas où (value_max = 0) AVANT d'exécuter la boucle.

- Le dernier problème majeur reste la conversion de binaire à string. En fait, je pense que le mieux est de calculer (via une fonction) la taille de la string à partir de la taille du nombre binaire. Ensuite, dans le code principal, le programmeur alloue la mémoire nécessaire pour la string (indiqué par la fonction), et enfin appelle BinToStr pour convertir le nombre binaire en string dans la mémoire qui vient juste d'être allouée.
A ce propos, la longueur d'un nombre x en binaire s'exprime par ln(x)/ln(2)+1 (en bits), et en décimal par ln(x)/ln(10)+1. Or, si on ne considère par les "+1", en faisant le rapport de l'un et l'autre on trouve (ln(x)/ln(2))/(ln(x)/ln(10)) = ln(10)/ln(2) = cste. Ce qui veut dire qu'on peut exprimer la longueur du nombre en décimal par la longueur du nombre en binaire multiplié par une constante, la classe nan? Mais ça reste une approximation (déjà pas mal), parce qu'il se peut que dans certains cas il y ai un (ou plusieurs?) zéros tout à gauche de notre string... C'est quand même très satisfaisant comme algorithme et puis le programme pourra le reconvertir en binaire, même s'il y a des zéros en trop devant la string. Bien sûr s'il y a mieux je suis preneur...
Pour la veritable conversion en décimal après, ce n'est pas trop dur, c'est une succession de division par 10 etc... comme toute conversion d'une base vers une autre ;-).

- Introduire les entiers négatifs peut aussi être utile... à voir.


Voilà, et pour les opérations de bases il ne devrait pas y avoir de problème, toutes marchent sur le papier (à part la division ou ça se corse :s), mais on verra déjà...

Je ne peux coder que pendant les vacances, en période scolaire je n'ai pas de temps à accorder à la programmation. Au pire ce sera pour les grandes vacances, mais je serai là, je n'abandonne jamais un projet si bien commencé :D.

Twis++;

signaler à un administrateur
Commentaire de Bombela le 14/10/2004 17:10:51

OK Man !

T'as regardé ma source sur DelphiFr ?

@+

signaler à un administrateur
Commentaire de TheWhiteShadow le 14/10/2004 17:19:38

heureusement que tu me le dis, comme j'ai même pas le temps de regarder les nouvelles sources...

v aller voir ça, 2s ;-)

signaler à un administrateur
Commentaire de TheWhiteShadow le 14/10/2004 17:34:56

voilà j'ai fait un ptit tour et j'ai posté un commentaire ;)

donc pour l'instant voilà quoi, je pense que je pourrai continuer pendant les vacances qui viennent (qui sont proches quand même ;)), au moins de quoi faire l'addition et la conversion en string, de quoi faire des tests de rapidité entre les deux algos.

Twis++;

signaler à un administrateur
Commentaire de Bombela le 15/10/2004 10:46:28

Ok ok !

Je vais voir le commentaire !

@+

signaler à un administrateur
Commentaire de TheWhiteShadow le 05/11/2004 20:55:31

quelques précision pour le calcul de binaire à string (enfin résolu ^^), enfin pour calculer la taille du nombre en string (base 10) à partir de sa longueur en base 2:

d = [log(n)]+1 longueur du nombre n en base 10 ([] partie entière).
b longueur du nombre n en base 2 (par "longueur" on entend le nombre de chiffres qu'il faut pour écire le nombre).
n = 2^x avec x élément de réel.
on ne connait que b et [x]=b-1, et on cherche d.

on a donc 2^[x] <= n <= 2^([x]+1)
équivalent à log(2^[x]) <= log(n) <= log(2^([x]+1)) car log fct croissante
équivalent à ln(2)/ln(10)*[x] <= log(n) <= ln(2)/ln(10)*([x]+1)

or ln(2)/ln(10)*([x]+1) - ln(2)/ln(10)*[x] = ln(2)/ln(10) ~= 0.3 < 1
donc la longueur du nombre n en décimal (d = [log(n)]+1) peut s'exprimer par: [ln(2)/ln(10)*([x]+1)]+1 = [ln(2)/ln(10)*b]+1 avec au pire une erreur de 1.

Voilà! la conclusion c'est que maintenant on sait quelle taille allouer pour le nombre en décimal grâce à ce petit calcul, avec dans certains cas 1 octet en trop (ce qui entrenera un "0" devant le nombre décimal, mais ce n'est pas génant du tout).

Apres, un bidon calcul de conversion d'une base à l'autre et s'en est fini pour bin->str. ainsi on aura deja str->bin et bin->str... une rapide fonction d'addition et on pourra commencer les tests. jespere que je trouverai le temps de coder ces qq ptits trucs avant 2005... ;-)

aller ++, Twis

signaler à un administrateur
Commentaire de TheWhiteShadow le 21/11/2004 21:25:22

salut bombela,

question, ça te dérange que jécrive la partie algorithmique en pure assembleur (fichier .asm) et l'autre (fenetre etc...) en C?

personnellement je pense que c mieux, mais c pas encore sur que je vais le faire et je voulais juste savoir ce que tu en pensais.

++Twis;

signaler à un administrateur
Commentaire de Bombela le 21/11/2004 22:45:46

No problem !
That's good idea ;0)

Comme tu veux !
Le but, c'est que ça soit rapide et fonctionnel !

Mais si tu compile avec GCC, pas la peine de faire toi même de l'asm si tu  compile en optimisation maximale. GCC fais mieu qu'un être humain ! J'ai vérifié.

@+

signaler à un administrateur
Commentaire de TheWhiteShadow le 22/11/2004 19:15:58

ouais ok ben jverrai...
je pensais utiliser nasm pour compiler et visual c++ pour la partie C, mais bon ça reste à voir. mais je pense rester en .asm.

bref, ok ++Twis;

signaler à un administrateur
Commentaire de Bombela le 22/11/2004 20:32:08

Ok

signaler à un administrateur
Commentaire de TheWhiteShadow le 10/04/2005 15:56:22

t'as raison jvais tout refaire en ANSI C avec gcc dès que j'aurai le temps (c'est à dire pas tout de suite lol). au fait pour la division j'ai ma ptite idée maintenant... ça parait faisable en fait ;-)

sinon ça va chez toi? <- lol

bon jretourne à mes prbs d'algorithmiques... dailleurs ça msera vachement util pour cte source...

aller ++ twis

signaler à un administrateur
Commentaire de Bombela le 10/04/2005 18:22:41

Hehe... Vive gcc ;)
Je l'utilise beaucoup :D

@+

signaler à un administrateur
Commentaire de pYrAnNa le 18/08/2005 12:07:16

Génial cette source, j'ai justement besoin d'un algo pour convertir du décimal en hexadécimal.
Par contre je n'ai pas compris comment tu faisais la division d'un tres grand nombre décimal par 2^32.
Peux tu me donner plus de détail ? (juste sur ce point)
Merci d'avance.
(pour info je programme en ASM (masm32) une DLL de calcul rapide pour utiliser en VB).

signaler à un administrateur
Commentaire de TheWhiteShadow le 18/08/2005 13:22:09

ben tu copies le code =) lol non, je vais essayer de me souvenir le truc... ça fait qq mois quand même... encore un projet que j'aurai jamais le temps de finir d'ailleurs :(

ah ouiiiii... je viens de relire le code et je m'en rappelle maintenant, c'est vrai que c pas mal lol :) je te décris une itération:
en fait tu lis les caractères de ta string 1 par 1 (tu soustrais par 0x30 pour avoir le chiffre en binaire d'abord), et pour chaque caractère, tu multiplies le reste, c'est a dire eax (initialisé à 0) par 10 et tu y additionnes le chiffre binaire courant. maintenant l'astuce: si le fait de multiplier par 10 te donne un nombre plus grand que 2^32-1, alors tu as l'"extra" dans dl. si le fait d'additionner par le chiffre donne un eax plus petit, tu rajoutes 1 à dl. du coup, s'il n'y avait pas eu de sépération en deux registres, un shift de 32 à droite (= une division par 2^32) te donnerai exactement ce qu'il y'a dans dl (sauf que nous on l'a direct, si c pas beau :)) et ensuite ton dl tu le mets à la place du chiffre que du vient de lire, et tu recommences jusqu'à ce que tu ai fait toute la string. tu obtient ainsi ta string (en chiffres binaires) divisé par 2^32 par rapport à l'itération précédente. maintenant, ton dernier eax (dernier reste) forme 32 bits de ton nombre binaire.

et voilà, tu réitères ça sur ta string jusqu'à ce qu'elle soit inférieur à 2^32 ou dès qu'elle est à 0 je sais plus, et là tu as fini, en récupérant les eax à la fin de chaque itération, tu as ton nombre binaire. relis le code maintenant et ça devrait sembler clair :) (fait bien attention là où y'a des push et pop notamment un avec edx)

en fait, pour revenir à niveau de réfléxion plus abstrait, il faut se dire: je veux convertir un nombre décimal en nombre binaire, donc je vais faire des divisions successives par deux, et le reste de la division forme mon nombre binaire. mais comme on veut optimiser comme des oufs et qu'on a des registres 32 bits, on divise par 2^32 pour aller plus vite (héhé). sauf qu'on fait même pas les divisions puisque on tire parti de la multiplication par 10 qui fou l'extra dans un autre registre (héhéhé) donc franchement, je crois que j'y avais bien pensé à l'époque, je vois pas comment on peut faire mieux (héhéhéhé). bon bref lol =)

en tout cas si jsuis pas clair sur qqch hésite pas, et jveux bien que tu me montres ton projet à l'occaz (tu fais signes ou tu postes un commentaire ici pour me le dire pcq jai pu le temps de trainer sur codes sources). assembleur en force!!!!

TheWhiteShadow, Twis, guinux, bref comme vous voulez

signaler à un administrateur
Commentaire de TheWhiteShadow le 18/08/2005 13:37:33

oui je voulais aussi dire: pour faire les opérations de base genre + et -, on peut très bien utiliser la méthode école primaire, mais surtout pas pour * et /. en fait je dis ça pcq je sais maintenant qu'il existe des algos de psychopates ultra efficaces pour faire ça donc... sont surement dans the art of computer programming de donald knuth m'enfin... google est sûrement un meilleur ami ;)

signaler à un administrateur
Commentaire de Bombela le 18/08/2005 18:19:20

Ouaip... De beaux algos ;0)
Je me rappelle même pas de ce que j'ai fais de ma source qui additionne en décimal ;) Enfin, je l'ai pas effacer, je pense pas... Mais vus que je tourne sous linux maintenant, j'ai un peux laché delphi :D
TheWhiteShadow si tu veux la source suffit de le dire ! ;)

@+

signaler à un administrateur
Commentaire de TheWhiteShadow le 19/08/2005 09:15:17

lol figure toi que je suis aussi sous linux :) mais bah j'ai vraiment plus le temps pour rien là...

bonne journée!

Twis

signaler à un administrateur
Commentaire de Bombela le 19/08/2005 16:21:09

Ah le temps...
Tu connais la calculatrice console "bc" de linux ?
Elle est terrible !

signaler à un administrateur
Commentaire de TheWhiteShadow le 19/08/2005 17:42:48

lol jconnaissai po. jai tapé bc dans une console et apparemment c un parseur qui reste en console :) terrib tu dis? elle permet de faire quoi?

signaler à un administrateur
Commentaire de Bombela le 19/08/2005 18:07:17

Elle reste pas en console ! C'est une calculatrice ! Elle attend que tu tape quelque chose ;)
Ce qu'elle fait ? Tout. T'as essayé de taper 2^128^2 !
Pour tout savoir su bc ==> tape "man bc"

@+

signaler à un administrateur
Commentaire de TheWhiteShadow le 19/08/2005 18:16:45

oui oui j'avais compris qu'elle attendais une expression à parser... en effet par contre je viens de rentrer ce que tu proposes c'est vrai qu'elle a l'air sacrément balèze :) merci pour le trick, a+ et bonnes fin de vacs man!

signaler à un administrateur
Commentaire de pYrAnNa le 24/08/2005 17:38:05

Super génial cet algorythme. J'ai enfin tout compris. Merci pour tes explications. C'est justement ce que je recherchais.
J'ai fait avec des tests de rapidité, ca ne m'apporte rien pour l'addition, mais pour la multiplication et la division c'est évident que je vais y gagner en calculant en Héxadécimal.
Merci encore.

Ajouter un commentaire



Nos sponsors

Sondage...

CalendriCode

Juillet 2009
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Comparez les prix Nouvelle version

Photothèque Nouveau !



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,484 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.