Hexa et chaine

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Hexa et chaine

Message par Thyphoon »

Encore une question idiote du Thyphoon
j'ai une valeur hexa dans une variable
a$="$FFFFFF"
comment je peu la transformer en valeur décimal ?
avec la commande Val() ça ne fonctionne pas
et j'ai pas trouvé de commande comme bin(), Hex() mais qui transformerait en decimal ... Dec() n'existe pas ...
Quel est l'astuce ?
Merci d'avance
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Message par comtois »

N'oublies pas que CodeArchiv c'est ton ami :)

Code : Tout sélectionner

; English forum: http://purebasic.myforums.net/viewtopic.php?t=8828&highlight=
; Author: Froggerprogger
; Date: 23. December 2003

; Some notes:
; -----------
; There's no difference between a hex-value and a decimal value except for the notation. 
; The functions that are writing into a file do always request even binary numbers - as
; every function in a programming language - but they don't care if they are notated as
; e.g. (decimal) 32 or $20 or %100000 

; So you'll have to parse the string and get the value from it (there it is important,
; that it is notated as a hex-value) and then store this value to your file. 
; If you view the file-content with a HEX-Editor, you'll see the values in HEX-notation,
; but they have the same value as the decimal. 
; So e.g. you have a string that contains $20, you'll get the decimal value 32 from it
; and store the value 32 to file. 
; A Hex-Editor will view it as '20' again, but it's value to calculate with is still 32. 

; Here's a routine to get the decimal value from a string that contains Hex-data: 


; 23.12.2003 by Froggerprogger 
; parses from right to left and retrieves the value of a maximum of 8 chars 
; interpretated as a HEX-number or if a non-valid char or the end is reached. 
; it works case-insensitive, so 'af' = 'AF' 
Procedure GetValueFromHexString(str.s) 
  If Len(str) = 0 
    ProcedureReturn -1 
  EndIf 
  
  str = UCase(str) 
  
  Protected actCharAsc.l, result.l 
  Protected strLen.l      : strLen = Len(str) 
  Protected parseAct.l    : parseAct = @str + strLen - 1 
  Protected parseEnd.l    : parseEnd = parseStart - 7 
  Protected posFact.l     : posFact = 1 
  Protected radix.l       : radix = 16 
    
  actCharAsc = PeekB(parseAct)&$FF 
  
  While ((actCharAsc >= 48 And actCharAsc <= 57) Or (actCharAsc >= 65 And actCharAsc <= 70)) And parseAct >= parseEnd 
    If actCharAsc >= 65 
      actCharAsc - 7 
    EndIf 
    actCharAsc - 48 ; so '0'-'F' has values 0 - 15 
    result + posFact * actCharAsc 
    parseAct - 1 
    posFact * 16 
    actCharAsc = PeekB(parseAct)&$FF 
  Wend 
  
  ProcedureReturn result 
EndProcedure 

Debug GetValueFromHexString("(§/346&(=20") 
Debug GetValueFromHexString("$7FFffFFf") 
Debug GetValueFromHexString("$FFFFFF")
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Message par Le Soldat Inconnu »

Moi, j'ai fait ces 2 procedures (vous pouvez en faire une lib, c'est ce que j'ai fait)

Code : Tout sélectionner

ProcedureDLL HexVal(Txt.s) ; Convertir une chaine hexadécimal en valeur numérique
  Protected Val.l, n.l, Caractere.w
  Txt = LCase(Trim(RemoveString(Txt, "$")))
  Val = 0
  For n = 0 To Len(Txt) - 1
    Caractere = Asc(Mid(Txt, Len(Txt) - n ,1))
    If Caractere >= 97 And Caractere <= 102
      Val = Val | ((Caractere - 87) << (4 * n))
    ElseIf Caractere >= 48 And Caractere <= 57
      Val = Val | ((Caractere - 48) << (4 * n))
    EndIf
  Next
  ProcedureReturn Val
EndProcedure

ProcedureDLL BinVal(Txt.s) ; Convertir une chaine binaire en valeur numérique
  Protected Val.l, Chiffre.b
  Txt = LCase(Trim(RemoveString(Txt, "%")))
  Val = 0
  For n = 0 To Len(Txt) - 1
    Chiffre = Val(Mid(Txt, Len(Txt) - n ,1))
    Val = Val | (Chiffre << n)
  Next
  ProcedureReturn Val
EndProcedure
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Avatar de l’utilisateur
Chris
Messages : 3731
Inscription : sam. 24/janv./2004 14:54
Contact :

Message par Chris »

J'ai ça, trouvé dans CodeArchiv, le fichier s'appelle Bin&Hex_to_Decimal.pb.

Code : Tout sélectionner

Procedure HexVal(a$); - Convert a String in hexdecimal-format in numeric value 
  a$=Trim(UCase(a$)) 
  If Asc(a$)='$' 
    a$=Trim(Mid(a$,2,Len(a$)-1)) 
  EndIf 
  Result=0 
  *adr.BYTE=@a$ 
  For i=1 To Len(a$) 
    Result<<4 
    Select *adr\b 
      Case '0' 
      Case '1':Result+1 
      Case '2':Result+2 
      Case '3':Result+3 
      Case '4':Result+4 
      Case '5':Result+5 
      Case '6':Result+6 
      Case '7':Result+7 
      Case '8':Result+8 
      Case '9':Result+9 
      Case 'A':Result+10 
      Case 'B':Result+11 
      Case 'C':Result+12 
      Case 'D':Result+13 
      Case 'E':Result+14 
      Case 'F':Result+15 
      Default:i=Len(a$) 
    EndSelect 
    *adr+1 
  Next 
  ProcedureReturn Result 
EndProcedure

; Demo:

Debug HexVal("$12E")
Sinon, il me semble que quelqu'un avait posté un truc à ce sujet. (ZapMan, si ma mémoire est bonne).
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

merci :D

c'est genial
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

Encore plus court:

Code : Tout sélectionner

; By Nico 

Procedure Hex_to_Dec(Hex.s) 
  chaine$="0123456789ABCDEF" 
  *Pointeur = @Hex+1 
  For a= 1 To Len(Hex)-1 
    valeur = FindString(chaine$, PeekS(*Pointeur,1), 1) 
    *Pointeur=*Pointeur+1 
    res= res <<4  | valeur-1 
  Next 
  ProcedureReturn res 
EndProcedure 

Hexadecimal.s="$12ABCDEF" 
Debug Hex_to_Dec(Hexadecimal) 
Debug $12ABCDEF
:D
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

Pour les binaires, c'est encore plus simple:

Code : Tout sélectionner

; By Nico

Procedure Bin_to_Dec(Bin.s)
  *Pointeur = @Bin+1
  For a= 1 To Len(Bin)-1
    valeur=PeekB(*Pointeur) & %1
    res= res <<1  | valeur
    *Pointeur=*Pointeur+1
  Next
  ProcedureReturn res
EndProcedure

Binaire.s="%10010110111010100101"
Debug Bin_to_Dec(Binaire)
Debug %10010110111010100101
:D
brossden
Messages : 833
Inscription : lun. 26/janv./2004 14:37

Message par brossden »

Bonjour Nico

Sauf erreur de ma part :

Ta procedure ne fonctionne pas toujours
exemple :

Code : Tout sélectionner

; By Nico 

Procedure Hex_to_Dec(Hex.s) 
  chaine$="0123456789ABCDEF" 
  *Pointeur = @Hex+1 
  For a= 1 To Len(Hex)-1 
    valeur = FindString(chaine$, PeekS(*Pointeur,1), 1) 
    *Pointeur=*Pointeur+1 
    res= res <<4  | valeur-1 
  Next 
  ProcedureReturn res 
EndProcedure 

Hexadecimal.s="$1F" 
Debug          $1F
Debug Hex_to_Dec(Hexadecimal)

 
par contre si tu changes la ligne :
res= res <<4 | valeur-1
par
res= res <<4 + valeur-1

cela semble marcher à tous les coups !
Denis

Bonne Jounée à tous
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

La doc de PureBasic est peu locace sur la priorité des opérateurs

- Calcul arithmétique standard avec respect de la priorité des opérateurs et parenthèses : +, -, /, *, and, or, lsl, asl, lsr, asr
res= res <<4 | valeur-1 peut aussi être remplacé par

res= res <<4 | (valeur-1)

mais j'ai fait peu de tests et j'ai pas analysé le code complet.
brossden
Messages : 833
Inscription : lun. 26/janv./2004 14:37

Message par brossden »

Re Bonjour

Le plus court peut être aussi :

Code : Tout sélectionner

Procedure Hex_to_Dec(Hex.s) 
  For a= 1 To Len(Hex)-1 
    res= res <<4 | FindString("123456789ABCDEF", PeekS(@Hex+a,1), 1) 
  Next 
  ProcedureReturn res 
EndProcedure 
et dans le même esprit de simplification

Code : Tout sélectionner


Procedure Bin_to_Dec(Bin.s) 
  For a= 1 To Len(Bin)-1 
     res= res <<1  | (PeekB(@Bin+a) & %1) 
  Next 
  ProcedureReturn res 
EndProcedure 

Denis

Bonne Jounée à tous
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Message par nico »

Merci Brossden et Denis pour l'erreur découverte et sa correction, j'ai vérifier la procédure , c'est bien un problème de parenthèse.

J'évite toujours de concaténer plusieurs fonctions pour la compréhension du code.

:)
brossden
Messages : 833
Inscription : lun. 26/janv./2004 14:37

Message par brossden »

Bonjour Nico

Je suis d'accord avec toi pour le fait d'être clair dans un développement, mais alors va au bout de ton raisonnement et évite de passer par des pointeurs mémoire et autre rotation de bite qui ne sont clair que pour des gens rompus au language machine !

Je pense que la solution qui suit est plus simple à comprendre pour le commun des mortels dont je fais partie, et tout aussi rapide.
Je souligne par contre ton astuce qui utilise FindString, qui est superbe, et c'est ce qui m'a d'ailleur donné envie de faire cette mise au point.

Code : Tout sélectionner


Procedure.l Hex2Dec(MotHex.s) 
  
  ; Répétition pour chacun des caractères du mot hexa  
  For n=1 To Len(MotHex) 
    
    ; Extraction du caractère hexa ou Quartet et mise en forme pour la casse !    
    Quartet.s = UCase(Mid(MotHex,n,1)) 
    
    ; Affectation de sa valeur décimale au quartet. FindString renvoie la position du quartet 
    ;dans la chaine qui se trouve correspondre à sa valeur décimale. 
    ;Pour 0 qui n'est pas dans la chaine FindString renvoit naturellement 0. 
    ValQuartet.b = FindString("123456789ABCDEF",Quartet,1) 
    
    ; Calcul de la valeur décimale du mot hexa, à chaque fois que l'on rajoute un quartet à un mot hexa, 
    ; sa valeur précédente est multipliée par 16 plus le nouveau quartet 
    ValDec.l = ValDec * 16 + ValQuartet 
    
    ; Répétition jusqu'a la fin du mot hexa 
  Next 
  
  ProcedureReturn ValDec 
EndProcedure 

Debug $1FAA12 
Debug Hex2Dec("$1faa12") 
Une fois condensé et épuré des commentaires le code peut être ramené à cela :

Code : Tout sélectionner


Procedure.l Hex2Dec(MotHex.s) 
  For n=1 To Len(MotHex) 
    ValDec.l * 16 + FindString("123456789ABCDEF",UCase(Mid(MotHex,n,1)),1)
  Next 
  ProcedureReturn ValDec 
EndProcedure 

Debug $1FAA12 
Debug Hex2Dec("$1faa12") 

Pour être vraiment honnête j'adore les procédures qui se résument à trois quatre lignes de code bien senties !

Bravo encore Nico !!
Denis

Bonne Jounée à tous
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

On aurait voulu lancer un concour de code on aurait pas fait mieux !
ça c'est genial tout le monde apporte une solution et au final on a un truc super optimisé et simple !!!
Merci a tous :D On devrait faire ça plus souvant
Avatar de l’utilisateur
Chris
Messages : 3731
Inscription : sam. 24/janv./2004 14:54
Contact :

Message par Chris »

brossden a écrit :...évite de passer par des pointeurs mémoire et autre rotation de bite...
Ca doit être très douloureux, ça, non...? :roll:
(Enfin... Tout dépend du nombre de tours!) :lol:
brossden
Messages : 833
Inscription : lun. 26/janv./2004 14:37

Message par brossden »

Scuze Chris

Il est vrai qu'il faut lire "bit" et non "bite", désolé pour les fautes d'orthographe :oops:
Denis

Bonne Jounée à tous
Répondre