Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Trabajar Con Bytes

Iniciado por [EX3], 06 de Octubre de 2004, 02:39:28 AM

« anterior - próximo »

[EX3]

 
Cita de: "sés"No estoy seguro, pero... ¿VB no tiene operadores booleanos? Con eso creo que te serviría.
Estos son los operadores de Visual Basic 6:
  • Operadores artimeticos: ^, *, /, \, Mod, +, -
  • Operadores de comparacion: <, <=, >, >=, =, <>
  • Operadores de concatenacion: &, +
  • Operadores logicos: And, Eqv, Imp, Not, Or, Xor

    Una de dos, o te refieres a los de comparacion o esque no existen en VB.

    Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

sés

 Me refiero a: AND, OR, NOT y XOR
Creo recordar que funcionan como operadores booleanos si se utilizan con enteros.

Haz una prueba:
PRINT 1 OR 2
PRINT 6 AND 3
PRINT 7 XOR 2


Esto debería imprimir (si no me he confundido):
3
2
5
Soy indeciso... ¿o no?

[EX3]

 PRINT 1 OR 2
PRINT 6 AND 3
PRINT 7 XOR 2

3
2
5

Correcto  :)

Entonces con estos operadores podria realizar desplazamientos de bits?

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

sés

 No, no puedes hacer desplazamientos, pero te pueden ayudar a resolver tu problema con los números negativos.

No recuerdo bien VB, pero creo que sería algo como:
Dim b(100) AS Byte ; el array de bytes
Dim res, b0, b1, b2 AS Long ; TODAS como Long

; meter cada byte en un long
b0 = b(1)
b1 = b(2)
b2 = b(3)
b3 = b(4)

; crear el long
res = b0 AND 255 ; b0 & 0xff
res = res OR ((b1 AND 255) * 256) ; res | ((b1 & 0xff) << 8)
res = res OR ((b2 AND 65535) * 65536)  ; res | ((b2 & 0xff) << 16)
res = res OR ((b3 AND 16777215) * 16777216)  ; res | ((b3 & 0xff) << 24)


Al hacer el AND, se eliminan los bits superiores que indican el signo, por lo que CREO que debería funcionar si no me he confundido al escribir ^_^
Soy indeciso... ¿o no?

[EX3]

 El codigo funciona pero tambien falla con los negativos. Gracias por el intento ;)

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

sés

 Je,je... me confundí, los AND deberían ser todos con 255.

Te lo pongo de nuevo corregido y algo más clarito:

Dim b(100) AS Byte; el array de bytes
Dim res, b0, b1, b2 AS Long; TODAS como Long

; meter cada byte en un long
b0 = b(1) AND 255 ; b(1) & 0xff
b1 = b(2) AND 255 ; b(2) & 0xff
b2 = b(3) AND 255 ; b(3) & 0xff
b3 = b(4) AND 255 ; b(4) & 0xff

; crear el long, es el mismo código que ya te pusieron más arriba
; la diferencia es que b0, b1, b2 y b3 son positivos all hacerles AND con 255
res = b0 ; b0
res = res OR (b1 * 256); res | (b1 << 8)
res = res OR (b2 * 65536) ; res | (b2 << 16)
res = res OR (b3 * 16777216) ; res | (b3 << 24)
Soy indeciso... ¿o no?

[EX3]

 Aun con la correccion el valor sigue siendo incorrecto. Mira a ver, ke a lo mejor he puesto algo mal en el codigo y no me he dado cuenta:
'Lee un entero largo del buffer de datos:
Public Sub Read_LONG(Var As Long, Pos As Long)
On Error Resume Next
Dim b(3) As Long

If Pos + 3 > UBound(Buffer) Then Exit Sub

b(0) = Buffer(Pos) And 255
b(1) = Buffer(Pos + 1) And 255
b(2) = Buffer(Pos + 2) And 255
b(3) = Buffer(Pos + 3) And 255

Var = b(0)
Var = Var Or (b(1) * 256)
Var = Var Or (b(2) * 65536)
Var = Var Or (b(3) * 16777216)
End Sub

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

sés

 No veo ningún error (de escritura ^_^).

Si tuviera VB podría probar y decirte cómo hacerlo... o por lo menos ver porqué falla. De todas formas, si me dices qué valores hay en el array y el resultado, puede que vea algo.
Soy indeciso... ¿o no?

[EX3]

 Valor Original: -40961024
Bytes en Hexadecimal: 0x00, 0xFC, 0x8E, 0xFD
Bytes en Enteros: 0, 252, 142, 253
Valor devuelto por la funcion: 9370624

Para hacer pruebas en tiempo de ejecucion te podria pasar un pequeño programa que hice para realizar pruebas de codigo que lleva integrado el M$ Script Control con el VBScript y este aun no soportando tipos de datos (solo trabaja con Variants) tiene toda las instrucciones del VB para la tarea en cuestion y se puede trabajar datos especificos mediante conversiones CStr(), CByte(), CLng()... Si te interesa lo subo a mi ftp y te lo bajas, es ideal para realizar pruebas con codigos sin tener que tener instalado el VB  :)

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

sés

 No sé si te has fijado en lo que te sale:
9370624 = 8EFC00h
Curioso, ¿no? Es el valor que deberías tener en Val antes de hacer nada con el cuarto byte (FDh). Es como si te lo hubieras comido.

Comprueba que b(3) tenga el valor 253 (FDh).
b(3) * 16777216 tiene que valer -50331648 (FD000000h).

O sea:
Var = b(0)
b(0) = 0
Var = 0
Var = Var Or (b(1) * 256)
b(1) = 252 (000000FCh)
b(1) * 256 = 64512 (0000FC00h)
Var = 64512 (0000FC00h)
Var = Var Or (b(2) * 65536)
b(2) = 142 (0000008Eh)
b(2) * 65536 = 9306112 (008E0000h)
Var = 9370624 (008EFC00h) ¿TE SUENA?
Var = Var Or (b(3) * 16777216)
b(3) = 253 (000000FDh)
b(3) * 16777216 = -50331648 (FD000000h)
Var = -40961024 (FD8EFC00h)
Soy indeciso... ¿o no?

sés

 Que cosas, si tengo el Access. He estado probando y ya sé lo que pasa; Hay un desbordamiento en el 4º byte.
Al hacer:
  b(3) * 16777216

estamos haciendo:
  253 * 16777216 = 4244635648 (FD000000)

Lo que nos provoca un desbordamiento porque en un Long no se puede representar ese número (el máximo es 2147483647 ó 0x7FFFFFFF).

La única solución es montar el último byte de otra forma, así:

Dim msk As Long
Dim bit As Long
bit = &H80000000
msk = &H80

While msk <> 0
   If (b(3) And msk) <> 0 Then
       Var = Var Or bit
   End If
   msk = msk \ 2 And &H7F
   bit = bit \ 2 And &H7F000000
Wend

Utilizando solo operaciones booleanas y divisiones (que no provocan desbordamiento ;))

Te pongo el código completo con el que he probado:
Dim Buffer(10) As Byte
Dim b(4) As Long
Dim pos As Integer
Dim Var As Long
   
Buffer(0) = &H0     ' 0
Buffer(1) = &HFC    ' 252
Buffer(2) = &H8E    ' 142
Buffer(3) = &HFD    ' 253
   
pos = 0
   
b(0) = Buffer(pos) And &HFF
b(1) = Buffer(pos + 1) And &HFF
b(2) = Buffer(pos + 2) And &HFF
b(3) = Buffer(pos + 3) And &HFF
   
Var = b(0)
Var = Var Or (b(1) * 256)
Var = Var Or (b(2) * 65536)
   
' caso especial
Dim msk As Long
Dim bit As Long
bit = &H80000000
msk = &H80
While msk <> 0
   If (b(3) And msk) <> 0 Then
       Var = Var Or bit
   End If
   msk = msk \ 2 And &H7F
   bit = bit \ 2 And &H7F000000
Wend


Esto lo he probado y me da el resultado correcto: -40961024
Soy indeciso... ¿o no?

[EX3]

 Correcto, funciona  :) Se ve que al usar el On Error Resume Next no me percate, ni aun viendo la operacion, el error de desbordamiento. Pues muchas gracias por tu ayuda. Ahora solo me falta terminar lo de la lectura y escritura de coma flotante y ya podria trabajar con bytes en el motor.

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

sés

 *arf, arf...* Me alegro de que funcione de una vez.

De todas formas, si vas a realizar estas operaciones muchas veces, intenta optimizar. Eso no creo que sea precisamente rápido... además es VB :huh:

Seguramente puedas optimizar algunas cosas. Además, sabiendo cuál era el problema... y tú que sabes VB :P, a lo mejor se te ocurre otra solución; a mí solo se me ocurrió esa "ñapa".

Te digo una que se me acaba de ocurrir:
Utiliza un byte más (por ejemplo) para los números. Guarda los bytes de la misma forma, excepto el 4º, al que le quitas el bit de signo (así no habrá desbordamiento al multiplicar). En ese byte extra indica el bit de signo (0 ó 1).
Utilizas un byte más para los Long (para el resto no te hace falta, supongo), pero es más rápido.
Soy indeciso... ¿o no?

[EX3]

 
Cita de: "sés"Seguramente puedas optimizar algunas cosas. Además, sabiendo cuál era el problema... y tú que sabes VB :P, a lo mejor se te ocurre otra solución; a mí solo se me ocurrió esa "ñapa".
Vale  :P , se programar en VB "mas o menos con soltura" pero no a un nivel tan avanzado como para tratar temas "tan complejos" para mi como esta siendo esto de trabajar con bytes. Yo de momento este codigo lo dejare como esta ya que al menos funciona y aparte de servir para el motor me sirve para otros programas que tengo por ahi y que esta funcion les vendra de perlas.

Si resultase muy lento el trabajar datos de esta manera, a nivel de bytes en VB, recurriria otra a vez a los "comodos" Variants aun ocupando estos mas espacio de lo debido. Sobre lo del byte de mas para almacenar el signo del numero me parece una buena idea  :) , ya de paso podria improvisar y hacerme tb un formato propio para almacenar los numero de coma flotante (mediante alguna ñapa, claro) y un problema menos. Cuando tenga un ratito trasteo un poco con la idea.

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

sés

 Aquí tienes una versión mejorada... y más lógica de los famosos bytes.

Te pongo la parte del último byte, que es la que cambia
' caso especial
Dim signo As Long
If (b(3) And &H80) <> 0 Then
   signo = &H80000000
Else
   signo = 0
End If
b(3) = b(3) And &H7F
Var = Var Or (b(3) * 16777216) Or signo


Como ves te puedes olvidar de eso de añadir un byte para el signo.

La verdad es que no sé en qué estaba pensando cuando hice lo otro... en fin, mis neuronas debían estar de vacaciones (genial)
Soy indeciso... ¿o no?






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.