2009-11-20 11 views
6

Necesito realizar un desplazamiento circular a la izquierda de un entero de 64 bits en JavaScript. Sin embargo: los números¿Cómo simulo una rotación a nivel de bits de un entero de 64 bits (sin signo) en JavaScript?

  • JavaScript son dobles
  • JavaScript los convierte en enteros con signo de 32 bits cuando se inicia con la < < y el >> y el >>> y el ~ y todos los bits haciendo girar negocio. Y luego vuelve al doble cuando terminas. Creo.
  • No quiero el letrero. Y definitivamente no quiero los bits decimales. Pero definitivamente quiero 64 bits.

Entonces, ¿cómo realizo una rotación a la izquierda en modo bit de un valor de 64 bits?

+0

¿Sabe usted para asegurarse de que su Javascript siempre se ejecuta en una plataforma de 64 bits? – Amber

+1

p.s. Voto a favor de cualquiera que me diga que no haga esto en JavaScript. ¡No es útil! Y * sé * que este no es el tipo de tarea para la cual JavaScript es adecuado. Pero necesito hacerlo de todos modos. KTHXBAI. – Jeff

+0

no es que yo te crea, pero si JavaScript lo almacena en un doble, entonces es un doble no un int de 64 bits (independientemente de la señal). –

Respuesta

12

Mantenga su número de 64 bits como mitades altas y bajas separadas. Para girar a la izquierda N cuando N < 32:

hi_rot = ((hi << N) | (lo >>> (32-N))) & (0xFFFFFFFF)

lo_rot = ((lo << N) | (hi >>> (32-N))) & (0xFFFFFFFF)

si n> = 32, entonces restar 32 a partir de N, intercambiar hi y lo, y luego hacer lo anterior.

+0

Me gusta esta forma de hacerlo, pero ¿el hecho de que los números estén firmados causará algún problema? El bit más significativo almacena el signo. – Jeff

+0

Oh, dijiste menos de 32. Parece que eso soluciona el problema. – Jeff

+1

El único problema con esto es que '& (0xFFFFFFFF)' no funciona aquí. Si desea hacer que los números no estén firmados, use '>>> 0' en su lugar. –

4

Creo que sí, aunque no es la manera más eficiente, convertir el número a una cadena en formato binario (64 bits), usar subcadena para mover el carácter al principio y anexarlo al final (para girar a la izquierda) y convierte la forma binaria de nuevo a número. Estoy seguro de que puede averiguar cómo convertir un número decimal a su forma binaria en una cadena y viceversa.

+0

Supongo que estoy pidiendo un voto hacia abajo? :-) – Murali

+0

+1: es una solución hacky para un problema realmente extraño. –

+2

Nah, es una solución legítima, incluso si no es el tipo de solución que estoy esperando. No hay votos negativos para ti. – Jeff

0

La única forma en que creo que se puede hacer es crear una clase int64 que internamente contenga dos enteros de 32 bits y realice el cambio llevando entre ellos.

0

Aquí hay una rotación basada en valores.

double d = 12345678901.0; 
// get high int bits in hi, and the low in 
int hi = (int)(d/16.0/16.0/16.0/16.0); 
int low = (int)d; 

int rot = 3; // thus * 8 
int newhi = (low >> (32 - rot)) | (hi << rot); 
int newlow = (hi >> (32 - rot)) | (low << rot); 

double newdouble = ((double)hi * 16.0 * 16.0 * 16.0 * 16.0) + (double)low; 
+0

Bueno, eso es una versión de C#, y debido a las int firmadas, el último paso no funciona como se esperaba. De hecho, lo más probable es que tampoco funcione para éter de dobles negativos ... –

+0

El uso de operación aritmética es muy lento, especialmente cuando se quiere convertir una gran cantidad de bytes, p. datos de imagen, que no es una solución práctica. –

1

Como @Doug Currie puso necesita para representar el número de 64 bits como dos números, y luego hacer las operaciones bit a bit sobre ellos. El código que he usado es:

//Constructor for a Long.. 
function Long(high, low) { 
    //note: doing "or 0", truncates to 32 bit signed 
    //big-endian 2's complement int.. 
    this._high = high | 0; 
    this._low = low | 0; 
} 
Long.prototype.rotateLeft = function(bits) { 
    var newHigh; 
    if(bits === 32){ //just switch high and low over in this case.. 
     newHigh = this._low; 
     this._low = this._high; 
     this._high = newHigh; 
    } else { 
     newHigh = (this._high << bits) | (this._low >>> (32-bits)); 
     this._low = (this._low << bits) | (this._high >>> (32-bits)); 
     this._high = newHigh; 
    } 
    return this; //for chaining.. 
}; 
//Rotates the bits of this word round to the right (max 32).. 
Long.prototype.rotateRight = function(bits) { 
    var newHigh; 
    if(bits === 32){ //just switch high and low over in this case.. 
     newHigh = this._low; 
     this._low = this._high; 
     this._high = newHigh; 
    } else { 
     newHigh = (this._low << (32-bits)) | (this._high >>> bits); 
     this._low = (this._high << (32-bits)) | (this._low >>> bits); 
     this._high = newHigh; 
    } 
    return this; //for chaining.. 
}; 

para usarlo intente ejecutar: console.log(new Long(0,1).rotateLeft(4)); continuación, la inspección de las propiedades _high y GIRATORIO BAJO.

0

me gustaría probar esto:

function rotate(hi,lo,n) { 
    var N = n/%32; 
    if(Math.floor(n/32)%2) { 
     var hi_rot = ((hi << N) | (lo >>> (32-N))) & (~0); 
     var lo_rot = ((lo << N) | (hi >>> (32-N))) & (~0); 
    } else { 
     var hi_rot = ((lo << N) | (hi >>> (32-N))) & (~0); 
     var lo_rot = ((hi << N) | (lo >>> (32-N))) & (~0); 
    } 
    return (hi_rot<<32)+lo_rot; 
} 
Cuestiones relacionadas