Ya es hora de que escriba algo de lo que hago día a día en mi curro a nivel técnico. Me he visto en una situación bastante engorrosa para descifrar en un ratillo una forma de convertir números decimales (enteros de toda la vida) en un valor binario de 64 bits. Un bit es la unidad mínima de información digital, y tiene valor 0 o 1, que son los dos valores de voltaje que se usa a nivel electrónico (encendido-apagado). Estos valores forman valores complejos que se leen a una velocidad de infarto hoy en día. Es la base de cualquier unidad de información. Pero joder, usar decimales de 64 bits es algo que hasta hace relativamente poco no se ha podido hacer, porque ningún lenguaje de programación hasta Java o Visual .NET ha soportado la operación directa con tanto dígito.
Ahora, cuando quieres convertir un binario a su forma decimal, si este número tiene 64 bits (es decir, 64 unos y ceros), es una pesadilla nivel informático. La operación consiste en ir dividiendo ese número entero entre 2 y quedarse con el resultado (si es par o impar), que define si se pone un cero o un uno en esa posición (si la división es exacta, se pone un cero, de lo contrario da un uno). Si la división es inexacta, para la siguiente operación nos quedamos con el número absoluto (Es decir, que si una división nos da 12,7 o 12, 4 nos da igual: nos quedamos con el 12), para volver a dividir hasta que ya no nos sea posible, es decir, que el número a dividir sea menor o igual a 2.
Cuando ya tenemos todos los restos, invertimos la cadena al revés (el binario se lee de derecha a izquierda, como los japoneses), y ahora viene lo más divertido: si el número que queremos pasar a binario es negativo (lo que me ha pasado a mi), se hace exactamente lo mismo (dividir entre dos hasta llegar a cero), y luego invertimos ceros y unos salvo el más a la derecha. ¡Toma ya!. Y como a mi me ha costado horrores, voy a dejar el código que me he currado al respecto en Visual Basic .NET, para ver si puedo ayudar a algún alma desamparada. Lo de coger el “valor absoluto” al dividir lo he hecho muy cutre (con strings), pero me fio más que de cualquier función matemática. Y el caso es que funciona!.
Private Function DecimalABinario(ByVal ValorDecimal As Decimal) As String
Dim Binario As String = ""
Dim stringDivision As String = "", posComa As Integer = 0
Dim Valor As Decimal = ValorDecimal
Dim bEsNegativo As Boolean = (Valor < 0)
If bEsNegativo Then Valor = -Valor 'Se positiva el negativo
Do While (Valor >= 2)
Binario += IIf(esPar(Valor), "0", "1")
stringDivision = CDec((Valor / 2)).ToString.Trim
posComa = InStr(stringDivision, ",")
If (posComa > 0) Then
Valor = CDec(Left(stringDivision, posComa - 1))
Else
Valor = (Valor / 2)
End If
Loop
Binario += IIf(Valor < 2, "1", "0")
'Se invierte la cadena
Binario = InvertirCadena(Binario)
'Completamos hasta 64 Bits
Dim lenBinario As Short = Len(Binario)
Dim Maximo As Short = 64
Dim i As Integer
For i = (lenBinario + 1) To Maximo : Binario = "0" & Binario : Next i
If bEsNegativo Then ‘El ultimo dígito se cambia en caso de ser negativo
Binario = Left(Binario, 63) & IIf(Right(Binario, 1) = "0", "1", "0")
Binario = InvertirBinario(Binario)
End If
Return Binario
End Function
Private Function esPar(ByVal Numero As Decimal) As Boolean
Dim miNumero As Short = Val(Right(Numero.ToString.Trim, 1))
Dim bPar As Boolean = ((miNumero = 0) Or (miNumero = 2) Or (miNumero = 4) Or (miNumero = 6) Or (miNumero = 8))
Return bPar
End Function
Private Function InvertirCadena(ByVal strCadena As String) As String
strCadena = strCadena.Trim
Dim newCadena As String = ""
Dim PosActual As Integer = Len(strCadena)
Do While PosActual >= 1
newCadena &= Mid(strCadena, PosActual, 1)
PosActual -= 1
Loop
Return newCadena
End Function
Private Function InvertirBinario(ByVal stringBinario As String) As String
Dim NewCadena As String = "", charActual As Char = ""
Dim PosMax As Short = 0, PosActual As Short = 0
Dim i As Short = 0
stringBinario = stringBinario.Trim
PosMax = Len(stringBinario.Trim)
PosActual = 1
Do While PosActual <= PosMax
charActual = Mid(stringBinario.Trim, PosActual, 1)
Select Case charActual
Case "0"
NewCadena += "1"
Case "1"
NewCadena += "0"
End Select
PosActual += 1
Loop
Return NewCadena
End Function
Ahora, cuando quieres convertir un binario a su forma decimal, si este número tiene 64 bits (es decir, 64 unos y ceros), es una pesadilla nivel informático. La operación consiste en ir dividiendo ese número entero entre 2 y quedarse con el resultado (si es par o impar), que define si se pone un cero o un uno en esa posición (si la división es exacta, se pone un cero, de lo contrario da un uno). Si la división es inexacta, para la siguiente operación nos quedamos con el número absoluto (Es decir, que si una división nos da 12,7 o 12, 4 nos da igual: nos quedamos con el 12), para volver a dividir hasta que ya no nos sea posible, es decir, que el número a dividir sea menor o igual a 2.
Cuando ya tenemos todos los restos, invertimos la cadena al revés (el binario se lee de derecha a izquierda, como los japoneses), y ahora viene lo más divertido: si el número que queremos pasar a binario es negativo (lo que me ha pasado a mi), se hace exactamente lo mismo (dividir entre dos hasta llegar a cero), y luego invertimos ceros y unos salvo el más a la derecha. ¡Toma ya!. Y como a mi me ha costado horrores, voy a dejar el código que me he currado al respecto en Visual Basic .NET, para ver si puedo ayudar a algún alma desamparada. Lo de coger el “valor absoluto” al dividir lo he hecho muy cutre (con strings), pero me fio más que de cualquier función matemática. Y el caso es que funciona!.
Private Function DecimalABinario(ByVal ValorDecimal As Decimal) As String
Dim Binario As String = ""
Dim stringDivision As String = "", posComa As Integer = 0
Dim Valor As Decimal = ValorDecimal
Dim bEsNegativo As Boolean = (Valor < 0)
If bEsNegativo Then Valor = -Valor 'Se positiva el negativo
Do While (Valor >= 2)
Binario += IIf(esPar(Valor), "0", "1")
stringDivision = CDec((Valor / 2)).ToString.Trim
posComa = InStr(stringDivision, ",")
If (posComa > 0) Then
Valor = CDec(Left(stringDivision, posComa - 1))
Else
Valor = (Valor / 2)
End If
Loop
Binario += IIf(Valor < 2, "1", "0")
'Se invierte la cadena
Binario = InvertirCadena(Binario)
'Completamos hasta 64 Bits
Dim lenBinario As Short = Len(Binario)
Dim Maximo As Short = 64
Dim i As Integer
For i = (lenBinario + 1) To Maximo : Binario = "0" & Binario : Next i
If bEsNegativo Then ‘El ultimo dígito se cambia en caso de ser negativo
Binario = Left(Binario, 63) & IIf(Right(Binario, 1) = "0", "1", "0")
Binario = InvertirBinario(Binario)
End If
Return Binario
End Function
Private Function esPar(ByVal Numero As Decimal) As Boolean
Dim miNumero As Short = Val(Right(Numero.ToString.Trim, 1))
Dim bPar As Boolean = ((miNumero = 0) Or (miNumero = 2) Or (miNumero = 4) Or (miNumero = 6) Or (miNumero = 8))
Return bPar
End Function
Private Function InvertirCadena(ByVal strCadena As String) As String
strCadena = strCadena.Trim
Dim newCadena As String = ""
Dim PosActual As Integer = Len(strCadena)
Do While PosActual >= 1
newCadena &= Mid(strCadena, PosActual, 1)
PosActual -= 1
Loop
Return newCadena
End Function
Private Function InvertirBinario(ByVal stringBinario As String) As String
Dim NewCadena As String = "", charActual As Char = ""
Dim PosMax As Short = 0, PosActual As Short = 0
Dim i As Short = 0
stringBinario = stringBinario.Trim
PosMax = Len(stringBinario.Trim)
PosActual = 1
Do While PosActual <= PosMax
charActual = Mid(stringBinario.Trim, PosActual, 1)
Select Case charActual
Case "0"
NewCadena += "1"
Case "1"
NewCadena += "0"
End Select
PosActual += 1
Loop
Return NewCadena
End Function
Y esta va de regalo:
Private Function BinarioADecimal(ByVal sB As String) As String
'Transforma un número Binario en su valor Decimal
sB = Trim(sB)
Dim M As Decimal = 1, V As Decimal = 0, i As Integer = 0, lB As Integer = Len(sB), nA As Integer = 0
For i = lB To 1 Step -1
nA = Val(Mid(sB, i, 1).Trim)
If nA = 1 Then V += M
M *= 2
Next i
BinarioADecimal = V.ToString.Trim
End Function
Bueno, ya me he quedao a gusto con la programación de la semana. Aunque a todos los que lean esto no entiendan ni papa.
Un abrazo.