Page 1 sur 2

Conversion d'octets signés en non signés

Publié : sam. 21/mai/2005 22:44
par Droopy
Quand j'utilise des fonctions logiques ( XOR / AND / OR ) sur des variables de type Byte, vu que PureBasic considère celles ci comme des variables signées, le résultat n'est pas facilement lisible .

Bref voici comment les convertir en non signés

Code : Tout sélectionner


Procedure SignedBinaryToUnsigned(Byte.b)
  If Byte & %10000000 
    Byte=Byte & %01111111
    Retour=Byte+128
  Else
    Retour=Byte
  EndIf
  ProcedureReturn Retour
EndProcedure
A tester avec ceci :

Code : Tout sélectionner

;/                                     Unsigned   Signed
Debug SignedBinaryToUnsigned(%00000000) ; 0         0
Debug SignedBinaryToUnsigned(%01111111) ; 127       127
Debug SignedBinaryToUnsigned(%10000000) ; 128       -128
Debug SignedBinaryToUnsigned(%11111111) ; 255       -1

Publié : dim. 22/mai/2005 0:10
par erix14
J'ai plus simple :D

Code : Tout sélectionner

Procedure SignedBinaryToUnsigned(Byte.b) 
	!MOV	 dword [esp+1],eax
   ProcedureReturn Retour 
EndProcedure 
;/                                     Unsigned   Signed 
Debug SignedBinaryToUnsigned(%00000000) ; 0         0 
Debug SignedBinaryToUnsigned(%01111111) ; 127       127 
Debug SignedBinaryToUnsigned(%10000000) ; 128       -128 
Debug SignedBinaryToUnsigned(%11111111) ; 255       -1

Publié : dim. 22/mai/2005 6:05
par Anonyme2
Y a plus simple en PB (même si ça ne saute pas au yeux), voir le message de Fred sur le forum anglais en 2003

http://forums.purebasic.com/english/vie ... ght=signed

Publié : dim. 22/mai/2005 7:10
par Droopy
Merci Erix14 et Denis pour vos réponses

Il y avait effectivement plus simple
Je dois dire que le code assembleur me laisse perplexe !

Code : Tout sélectionner

Procedure SignedBinaryToUnsigned(Byte.b)
  retour=Byte
  If retour < 0  
    retour + 256
EndIf
ProcedureReturn retour
EndProcedure

;/                                     Unsigned   Signed
Debug SignedBinaryToUnsigned(%00000000) ; 0         0
Debug SignedBinaryToUnsigned(%01111111) ; 127       127
Debug SignedBinaryToUnsigned(%10000000) ; 128       -128
Debug SignedBinaryToUnsigned(%11111111) ; 255       -1

Publié : dim. 22/mai/2005 7:15
par Droopy
Après relecture du forum US il y a encore plus simple

Code : Tout sélectionner

Procedure SignedBinaryToUnsigned(Byte.b)
retour=Byte & $FF
ProcedureReturn retour
EndProcedure
Code de Fred

Publié : dim. 22/mai/2005 7:27
par Anonyme2
Droopy a écrit :Après relecture du forum US il y a encore plus simple

Code : Tout sélectionner

Procedure SignedBinaryToUnsigned(Byte.b)
retour=Byte & $FF
ProcedureReturn retour
EndProcedure
Code de Fred

Plus simple

Code : Tout sélectionner

Procedure SignedBinaryToUnsigned(Byte.b)
   ProcedureReturn Byte & $FF
EndProcedure

Publié : dim. 22/mai/2005 7:43
par erix14
Bravo Denis, du remporte le premier prix de la catégorie procédure :D

Code : Tout sélectionner

Global Time1,Time2
Global a.b,b.l

Procedure SignedBinaryToUnsigned(byte.b) 
     If byte & %10000000 
          byte=byte & %01111111 
          Retour=byte+128 
     Else 
          Retour=byte 
     EndIf 
     ProcedureReturn Retour 
EndProcedure 

Procedure SignedBinaryToUnsignedASM(byte.b) 
     !MOV    dword [esp+1],eax 
ProcedureReturn Retour 
EndProcedure 

Procedure SignedBinaryToUnsignedDenis(byte.b) 
     ProcedureReturn byte & $FF 
EndProcedure

Procedure SignedBinaryToUnsignedFred(byte.b) 
     Retour=byte & $FF 
     ProcedureReturn Retour 
EndProcedure

If OpenWindow(1,200,200,350,200,#PB_Window_SystemMenu,"Programme de test") 
     Time1.l = GetTickCount_()
     For t=1 To 10000000
          ;/                                     Unsigned   Signed 
          b = SignedBinaryToUnsigned(%00000000) ; 0         0 
          b = SignedBinaryToUnsigned(%01111111) ; 127       127 
          b = SignedBinaryToUnsigned(%10000000) ; 128       -128 
          b = SignedBinaryToUnsigned(%11111111) ; 255       -1
     Next
     Time2.l = GetTickCount_()
     StartDrawing(WindowOutput()) 
     FrontColor(0,0,0)
     DrawingMode(1)
     Locate(20,10):DrawText("Durée Procedure Droopy (en ms) :")
     Locate(280,10):DrawText(Str(Time2-Time1))
     StopDrawing() 
     Time1.l = GetTickCount_()
     For t=1 To 10000000
          ;/                                     Unsigned   Signed 
          b = SignedBinaryToUnsignedASM(%00000000) ; 0         0 
          b = SignedBinaryToUnsignedASM(%01111111) ; 127       127 
          b = SignedBinaryToUnsignedASM(%10000000) ; 128       -128 
          b = SignedBinaryToUnsignedASM(%11111111) ; 255       -1
     Next
     Time2.l = GetTickCount_()
     StartDrawing(WindowOutput()) 
     FrontColor(0,0,0)
     DrawingMode(1)
     Locate(20,40):DrawText("Durée Procedure ASM (en ms) :")
     Locate(280,40):DrawText(Str(Time2-Time1))
     StopDrawing() 
     Time1.l = GetTickCount_()
     For t=1 To 10000000
          ;/                                     Unsigned   Signed 
          b = SignedBinaryToUnsignedDenis(%00000000) ; 0         0 
          b = SignedBinaryToUnsignedDenis(%01111111) ; 127       127 
          b = SignedBinaryToUnsignedDenis(%10000000) ; 128       -128 
          b = SignedBinaryToUnsignedDenis(%11111111) ; 255       -1
     Next
     Time2.l = GetTickCount_()
     StartDrawing(WindowOutput()) 
     FrontColor(0,0,0)
     DrawingMode(1)
     Locate(20,70):DrawText("Durée Procedure Denis (en ms) :")
     Locate(280,70):DrawText(Str(Time2-Time1))
     StopDrawing() 
     Time1.l = GetTickCount_()
     For t=1 To 10000000
          ;/                                     Unsigned   Signed 
          b = SignedBinaryToUnsignedFred(%00000000) ; 0         0 
          b = SignedBinaryToUnsignedFred(%01111111) ; 127       127 
          b = SignedBinaryToUnsignedFred(%10000000) ; 128       -128 
          b = SignedBinaryToUnsignedFred(%11111111) ; 255       -1
     Next
     Time2.l = GetTickCount_()
     StartDrawing(WindowOutput()) 
     FrontColor(0,0,0)
     DrawingMode(1)
     Locate(20,100):DrawText("Durée Procedure Fred (en ms) :")
     Locate(280,100):DrawText(Str(Time2-Time1))
     StopDrawing() 
     Time1.l = GetTickCount_()
     For t=1 To 10000000
          ;/              Unsigned   Signed 
          a = %00000000
          b = a & $FF      ; 0         0 
          a = %01111111
          b = a & $FF      ; 127       127 
          a = %10000000
          b = a & $FF      ; 128       -128 
          a = %11111111
          b = a & $FF      ; 255       -1
     Next
     Time2.l = GetTickCount_()
     StartDrawing(WindowOutput()) 
     FrontColor(0,0,0)
     DrawingMode(1)
     Locate(20,130):DrawText("Durée direct en PureBasic (en ms) :")
     Locate(280,130):DrawText(Str(Time2-Time1))
     StopDrawing() 
     Time1.l = GetTickCount_()
     For t=1 To 10000000
          ;/                       Unsigned   Signed 
          a = %00000000
          !MOV	 bl,byte [v_a]
          !AND	 ebx,255
          !MOV	 dword [v_b],ebx      ; 0         0 
          a = %01111111
          !MOV	 bl,byte [v_a]
          !AND	 ebx,255
          !MOV	 dword [v_b],ebx      ; 127       127
          a = %10000000
          !MOV	 bl,byte [v_a]
          !AND	 ebx,255
          !MOV	 dword [v_b],ebx     ; 128       -128 
          a = %11111111
          !MOV	 bl,byte [v_a]
          !AND	 ebx,255
          !MOV	 dword [v_b],ebx      ; 255       -1
     Next
     Time2.l = GetTickCount_()
     StartDrawing(WindowOutput()) 
     FrontColor(0,0,0)
     DrawingMode(1)
     Locate(20,160):DrawText("Durée direct en ASM (en ms) :")
     Locate(280,160):DrawText(Str(Time2-Time1))
     StopDrawing() 
     Repeat 
          EventID = WaitWindowEvent() 
     Until EventID = #PB_EventCloseWindow 
EndIf 

Publié : dim. 22/mai/2005 8:16
par Droopy
Effectivement, Denis a gagné :oops:

Je mettrais son code dans (ma) lib

Génial ton test de vitesse de procédure Erix, je met ce code de coté !

Publié : dim. 22/mai/2005 8:39
par Droopy
Me basant sur le code d'Erix14 j'ai créé cette procédure pour mesurer la durée d'exécution d'un bout de code.

Code : Tout sélectionner

; Return the the number of milliseconds between two call
; Cool to Optimize your code
; Idea from Erix14

Procedure MeasureInterval()
  Static time
  If time
    temp=time
    time=0
    ProcedureReturn GetTickCount_()-temp
  Else
    time = GetTickCount_()
  EndIf
EndProcedure

MeasureInterval()
For n=1 To 10000000 : Next 
Debug MeasureInterval()

Publié : dim. 22/mai/2005 9:03
par djes
En regardant le code assembleur avec PureASM, je suis quand même surpris de la taille de la procédure (et de ses initialisations). L'opération en elle-même ne prend au pire que trois instructions, par contre le reste de la procédure (initialisation et restauration de la pile), plus d'une vingtaine, dont une boucle et deux sauts! Autant dire que parler d'optimisation dans ces conditions me laisse un peu... perplexe!

Je me demande si on ne pourrait pas inventer une nouvelle instruction de procedure dont on créerait entièrement le code, sans que pure ne le génére. On pourrait demander à Fred... On pourrait l'appeler ProcedureASM(params) par exemple.

Publié : dim. 22/mai/2005 9:10
par erix14
Tu as fait une erreur dans ta procédure :

Code : Tout sélectionner

Procedure MeasureInterval() 
     Static time 
     If time 
          temp=time 
          time=0 
          ProcedureReturn GetTickCount_()-temp 
     Else 
          time = GetTickCount_() 
     EndIf 
EndProcedure 

MeasureInterval() 
Delay(1000) 
Debug MeasureInterval()
Delay(1000) 
Debug MeasureInterval() 
Delay(1000) 
Debug MeasureInterval() 
Delay(1000) 
Debug MeasureInterval() 
Delay(1000) 
Debug MeasureInterval() 
Delay(1000) 
Debug MeasureInterval() 
voici ma correction :

Code : Tout sélectionner

Procedure MeasureInterval() 
     Static time 
     If time 
          temp=time
          time = GetTickCount_()
          ProcedureReturn time-temp
     Else 
          time = GetTickCount_() 
     EndIf 
EndProcedure 

MeasureInterval() 
Delay(1000) 
Debug MeasureInterval()
Delay(1000) 
Debug MeasureInterval() 
Delay(1000) 
Debug MeasureInterval() 
Delay(1000) 
Debug MeasureInterval() 
Delay(1000) 
Debug MeasureInterval() 
Delay(1000) 
Debug MeasureInterval() 

Publié : dim. 22/mai/2005 9:13
par nico
Le Soldat inconnu avait fait un post dessus sur les conversions des nombres signésmais je ne retrouve pas!

[EDIT] c'est ici:

http://purebasic.hmt-forum.com/viewtopi ... mbre+signe

Publié : dim. 22/mai/2005 9:13
par Droopy
Cette procédure sert à mesurer le temps que met un bout de code à s'exécuter.

Une fois le code optimisé, on n'utilise plus cette procédure !

Publié : dim. 22/mai/2005 9:19
par Anonyme2
Droopy a écrit :Effectivement, Denis a gagné :oops:

Je mettrais son code dans (ma) lib

Génial ton test de vitesse de procédure Erix, je met ce code de coté !

Rendons à César...

C'est le code de Fred :D

Publié : dim. 22/mai/2005 9:22
par Droopy
Pour Erix : Je ne pense pas avoir fait d'erreur, en fait elle permet de mesurer le temps d'exécution de plusieurs bout de code non contigus.

Code : Tout sélectionner

MeasureInterval() ; Initialisation
Delay(500) 
Debug MeasureInterval() 

; On fait autre chose
Delay(250)

MeasureInterval() ; Initialisation
Delay(800) 
Debug MeasureInterval(