Page 1 sur 1

variable quad en Hexa : BUG ? [RESOLU]

Publié : mar. 31/juil./2007 16:18
par Fanator
Bonjour à tous.
Je poste mon bout de programme, il y a peut-être un bug.
Version PureBasic utilisée : V4.10 béta 2
Peut-être me suis-je trompé, si quelqu'un peut y regarder...

Code : Tout sélectionner

Dim tab(64)
b.q=9223372036854770    ; cette valeur passe
; b.q=9223372036854771    ; tout ce qui est supérieur à la valeur précédente
; b.q=9223372036854775807 ; ne passe pas correctement à la sortie du programme
x.q=0
Debug "b = " + StrQ(b) + ", en Hexadécimal =" + HexQ(b)
c$ = HexQ(b)
  ; décomposition de la variable hexadécimale
For i= 1 To Len(c$)
  Select Mid(c$,i,1)
    Case "0","1","2","3","4","5","6","7","8","9"
      tab(i)=Val(Mid(c$,i,1))
    Case "A"
      tab(i)=10
    Case "B"
      tab(i)=11
    Case "C"
      tab(i)=12
    Case "D"
      tab(i)=13
    Case "E"
      tab(i)=14
    Case "F"
      tab(i)=15
  EndSelect
  Debug "Pos" + Str(i) + "__" + Str(tab(i))
Next i

For i=1 To Len(c$)
  x = x + tab(i)*Pow(16,Len(c$)-i)
Next i
Debug x                                   ; x doit être égal à b
Debug HexQ(x) + " en décimal =" + StrQ(x)

Debug ""
End

Fanator

Publié : mar. 31/juil./2007 16:50
par Flype
en purebasic les entiers sont 'signés' et donc au delà d'une certaine valeur (127 pour un .b etc...) on passe en négatif. j'ai pas regardé plus que çà ton code mais ton problème semble être lié.

Publié : mar. 31/juil./2007 17:32
par Fanator
@Flype :
Je ne suis pas tout à fait d'accord.
Pow(2,31)-1=2147483647 valeur maxi pour un long : valeur correcte
Pow(2,63)-1 doit être égal à 9223372036854775807 valeur maxi pour un quad.
Pow(2,63)-1= $7FFF FFFF FFFF FFFF, il suffit de controler avec la calculatrice de windows ou autre.
Donc je pense qu'il y a un problème à partir d'une certaine valeur (voir le code)



Fanator

Publié : mar. 31/juil./2007 19:36
par Ollivier
L'erreur n'est pas dans HexQ()
Elle est dans l'opération

Code : Tout sélectionner

x + n * Pow(a, b) ; Erreur de bit de parité
Une erreur de bit de parité sûrement conséquente à Pow().

La solution actuelle consiste juste à 'sortir' Pow de ton calcul en décomposant ce calcul.
Tu stockes Pow(a, b) dans un Quad nommé Q.Q par exemple et tu effectues en suite ton calcul:

Code : Tout sélectionner

Q.Q = Pow(a, b)
x + n * Q
Sinon, pour ta part, tu utilises une puissance de 2 (16 = Pow(2, 4) ) alors ne t'embête pas avec des multiplications et des puissances : tu fais travailler le CPU pour rien!

Utilises les décalages et opé logiques, c'est carrément plus simple pour toi et pour ton CPU. J'ai remanié ton code:

Code : Tout sélectionner

Dim tab.Q(64)

;b.q=9223372036854770    ; cette valeur passe 
; b.q=9223372036854771    ; tout ce qui est supérieur à la valeur précédente 
; b.q=9223372036854774    ; BEN NON PUISQUE LA VALEUR CI-CONTRE FONCTIONNE !
; b.q=9223372036854775807 ; ne passe pas correctement à la sortie du programme 
x.q=0 
Debug "b = " + StrQ(b) + ", en Hexadécimal =" + HexQ(b) 
c$ = HexQ(b) 
  ; décomposition de la variable hexadécimale 
For i= 1 To Len(c$) 

  Select Mid(c$,i,1) 
    Case "0","1","2","3","4","5","6","7","8","9" 
      tab(i)=Val(Mid(c$,i,1)) 
    Case "A" 
      tab(i)=10 
    Case "B" 
      tab(i)=11 
    Case "C" 
      tab(i)=12 
    Case "D" 
      tab(i)=13 
    Case "E" 
      tab(i)=14 
    Case "F" 
      tab(i)=15 
  EndSelect 
  Debug "Pos" + Str(i) + "__" + Hex(tab(i)) 
Next i 

;For i=1 To Len(c$) 
;  x = x + tab(i)* Pow(16,Len(c$)-i) 
;Next i 

; ça doit être au moins 5 fois plus rapide en cycle d'horloge
For i = 1 To Len(c$)
  x << 4 ; Décaler de 4 bits à gauche c'est multiplier par 16
  x | Tab(i) : Les champs de bits entre x et Tab(i) ne se 
  ;                croisent pas dans l'addition donc opération OU
Next

Debug x                                   ; x doit être égal à b 
Debug StrQ(x) + " en hexadécimal =" + HexQ(x) 

Debug "" 
End 

Publié : mar. 31/juil./2007 20:07
par Flype
tu as parfaitement raison ollivier.

Code : Tout sélectionner

Q.Q = Pow(a, b)
x + n * Q
la raison précise est Pow() prends deux flottants comme arguments et renvoie un flottant (.f)

et le compilateur purebasic va faire des transformations de type qui peuvent provoquer des problèmes d'arrondis. Or, stocker le résultat de Pow() dans une variable .q force le compilateur à faire la multiplication avec un quad au lieu d'un float.

Publié : mar. 31/juil./2007 20:40
par Fanator
@Flype
@Ollivier


J'avais fini par trouver les floats à propos de Pow() dans l'aide, mais vous avez trouvé la réponse.
C'est bien mon bout de programme qui était bogué pas PureBasic.
Je vous remercie tous les 2 pour vous être pencher sur mon problème.


Bonne soirée à tous !