David_erh:
Yo utilizo un metodo muy similar para obtener la representación binaria de una variable numérica; me refiero a iterar sobre los bits de la variable con la potencia binaria correspondiente a cada posición. He visto aquí en el foro varios códigos publicados para hacer la conversión, pero adolecen de una característica que yo suelo necesitar: que también obtengan la representación binaria de un número negativo. Con el método que estás usando aquí, es posible, aunque es evidente que no estás interesado en ello, porque limitas el rango de la variable de entrada a un byte, lo que daría un valor incorrecto para el rango de la variable (255="11111111" y -1="11111111")...
Cita: ¿cuando se cumple que la sentencia es falsa????.
Tu duda está en:
Se trata de una comparación binaria, no una comparación lógica. Según tu analisis, pasaria esto:
Código:
For i = 0 To 7
' i = 0 por lo tanto (2 ^ i) = 1
' y puesto que lngNum = 10
If lngNum And 2 ^ i Then
' lngNum sería evaluado como True y
' (2 ^ i) también, ya que ambos son <> 0
Pues no. Se supone que las expresiones numéricas en un If son evaluadas a True, si son distintas de cero. Pero todo cambia con los operadores lógicos cuando las dos expresiones en la operación son numéricas. Los operadores realizan una comparación bit a bit. Esto es lo que realmente pasa:
Código:
For i = 0 To 7
' i = 0 por lo tanto los bits en (2 ^ i) son:
' 0000 0000 0000 0000 0000 0000 0000 0001
' y los bits en lngNum son:
' 0000 0000 0000 0000 0000 0000 0000 1010
If lngNum And 2 ^ i Then 'Se realiza una operación bit a bit:
' (2 ^ i)-> 0000 0000 0000 0000 0000 0000 0000 0001
' lngNum -> 0000 0000 0000 0000 0000 0000 0000 1010
' ------------------------------------------
' AND -> 0000 0000 0000 0000 0000 0000 0000 0000
' El resultado de la operación es 0, lo cual es evaluado a False
'Si i=3 entonces (2 ^ i) = 8, es decir:
' (2 ^ i)-> 0000 0000 0000 0000 0000 0000 0000 1000
' lngNum -> 0000 0000 0000 0000 0000 0000 0000 1010
' ------------------------------------------
' AND -> 0000 0000 0000 0000 0000 0000 0000 1000
' El resultado de la operación es 8, lo cual es evaluado a True
Entonces, para averiguar si el bit n en un número determinado es 1, tenemos que hacer la operación AND binaria entre dicho número y el resultado de 2 ^ n. Esto es muy útil, por ejemplo para obtener el estado de flags (muchas funciones de la API devuelven en un número long multiples indicadores de estado —hasta 32 posibles—).
Aquí pongo de nuevo tu cód. con comentarios añadidos y un par de correcciones:
Código:
Private Function Dec2Bin(sNumDec As String) As String
Dim i As Integer
Dim lngNum As Long
Dim sTmp As String
'lngNum = Val(sNumDec) *Cambiado
'No es que sea un purista, pero si la variable ha
'sido definida como long, la función de conversión
'a usar es Clng. Es más eficiente (cuando se itera
'sobre un bucle muy grande), pero aquí no se
'notará diferencia alguna.
lngNum = CLng(sNumDec)
sTmp = ""
'For i = 0 To 7 *Cambiado
'Como RsOfT señala, la representación binaria es
'incorrecta. Y lo es, porque el bucle comienza
'evaluando el bit menos significativo. La solución
'es muy simple: Utiliza un bucle en decremento.
For i = 7 To 0 Step -1
'*****************
'Nota: Aunque la variable que almacena el valor
'numérico ha sido declarada como long, la función
'como la tienes sólo aceptará rangos de byte
'(long: 32 bits, integer: 16 bits, byte: 8).
'Para que acepte rangos de integer, i debe comenzar con 15
'Pero si intentas obtener la representación de los
'32 bits de un long (i = 31) con este método, te saltará el
'error de overflow. Para evitarlo, tienes que determinar
'antes si el número es negativo, para saber si el
'bit más significativo es 1.
'Aquí es donde tú tienes duda.
'El operador AND, como lo estás interpretando tú,
'es como operador lógico. Pero el operador está
'haciendo una comparación binaria.
If lngNum And 2 ^ i Then
sTmp = sTmp & "1"
Else
sTmp = sTmp & "0"
End If
Next
Dec2Bin = sTmp
End Function
Saludos.