vbscript - net - << visual basic
Cambio de bit cuando no hay... operador de cambio de bit (3)
En la aritmética de dos complementos, el único impacto que tienen los valores negativos al dividir por 2 para desplazarse a la derecha: se producirá el cambio a la derecha previsto, pero también introducirá una nueva posición de 1 bit en el bit más significativo (MSB) para "mantener el valor negativo" - a menos que el valor original fuera -1, en cuyo caso todos los bits se convierten en 0. Entonces, para corregir esto, intente con el siguiente pseudocódigo:
rightshift(x) {
if x >= 0 return x / 2;
if x < -1 return x / 2 - MINVAL; # Strip out sign bit
# x must be -1, i.e. "all bits on"
return x - MINVAL;
}
MINVAL
debe ser el valor cuya representación consista en solo el MSB activado y todos los demás bits desactivados, que es -32768 para 16 bits. (Llamado así porque será el número representable más negativo usando el complemento de dos.) Curiosamente, agregar MINVAL
funciona igual que restarlo en el pseudocódigo anterior, ya que en la aritmética de dos complementos, x - y
= x + NOT(y) + 1
, y MINVAL == NOT(MINVAL) + 1
.
Los cambios a la izquierda usando multiplicación por 2 funcionan para los números negativos tan bien como lo hacen para los positivos.
Tengo que implementar una suma de comprobación (CRC16 CCITT) para verificar el contenido de un archivo. La suma de comprobación es bastante simple de implementar en C o Java gracias a los operadores << y >> y a los muchos ejemplos disponibles en la red.
El asunto es ... mi cálculo de suma de verificación debe implementarse en VBScript.
Mi experiencia con este lenguaje es casi nula, pero desde mi entendimiento, no hay nada provisto para hacer cambios de bit en VBScript. Por lo tanto, confío en multiplicaciones y divisiones por dos. Funciona bien excepto con valores negativos .
Ejecuté algunas pruebas y creo que VBScript maneja sus enteros de 16 bits con el complemento de dos.
P1: ¿alguien puede confirmarme esto (complemento de dos en VBScript)? No encontré información precisa del sitio web de MSDN.
Q2: ¿Es posible hacer un cambio de bit (derecha e izquierda) con operaciones matemáticas simples cuando el número negativo está codificado con el complemento de dos?
.
Muchas gracias, realmente me gustaría evitar un problema como tratar con enteros como matrices de ''1'' y ''0'' o llamar a alguna aplicación java / c de VBScript.
EDITAR gracias por la ayuda, busque a continuación mi implementación de un cambio a la derecha en VBScript:
Function rightShift(value,bits)
Dim res
res = 65535 AND value
If value>=0 Then
res = res / (2^bits)
Else If value=-1 Then
res = rightShift(res + 32768, bits - 1)
Else
res = rightShift(value / 2 + 32768, bits - 1)
End If
End If
rightShift = res AND 65535
End Function
Nota sobre el código anterior: el valor a veces excedía los 16 bits, por lo tanto tuve que enmascarar los bits no utilizados para evitar el desbordamiento ( AND 65535
).
Eso es muy lento, prueba esto. Lo siguiente funciona para valores> = 0 pero arrojará un subíndice de matriz fuera de límites para bitshifts> 14 bits y el código es:
dim ShiftArray
ShiftArray = Array(1, 2, 4, 8, 16, 32, 64, 128, 256, 512,
1024,2048,4096, 8192, 16384)
'' example usage
dim num
num = 17
num = num * ShiftArray(2) '' left shift 2 bits
num = num / ShiftArray(3) '' right shift 3 bits
Multiplique por el número de bits para desplazar el desplazamiento a la izquierda. Divide para el cambio a la derecha. Esta matriz funciona para enteros de 16 bits.
Para enteros de 32 bits, la matriz mostrará el subíndice de la matriz fuera de límites para bitshifts> 30 y es:
dim ShiftArray
ShiftArray = Array(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,
2048,4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288,
1048576, 2097152, 4194304, 8388608, 16777216, 33554432,
67108864, 134217728, 268435456, 536870912, 1073741824)
Esto no es una respuesta sino un comentario. La respuesta dada por @j_random_hacker funcionó para mí. Pero en los lenguajes que realizan divisiones enteras como C # (suponiendo que no se pueda usar el operador de desplazamiento a la derecha incorporado por la razón que sea) se debe redondear cuando x no es par.
static int MINVAL = (int) -0x80000000;
static int ShiftRight(int n,int bits)
{
//if (n >= 0) return n / (int)Math.Pow(2, bits);
//double temp = n / Math.Pow(2, bits);
//int r = (int) Math.Floor(temp);
//return r;
if (n >= 0) return n / 2;
if (n < -1) return (int)Math.Round(n / (double)2, MidpointRounding.AwayFromZero) - MINVAL;//+ (n%2==0?0:-1); // Strip out sign bit
// x must be -1, i.e. "all bits on"
return n - MINVAL;
}
Ahora sí, C # tiene operadores de turno incorporados, así que esto es solo un propósito educativo.