2010-09-29 17 views
6

¿Cómo escribo esta expresión C en J? (Donde x es entero de entrada, y a es variable temporal)¿Cómo escribo esta expresión C en J?

((a= ~x & (~x >> 1)) ^= a ? 0 : (a^(a & (a - 1))) | (a^(a & (a - 1))) << 1); 

.

Editar:

En una forma más legible:

int a = (~x) & ((~x) >> 1); 
    if (a == 0) return 0; 
    int b = a^(a & (a - 1)); 
    return b | (b << 1); 
+11

¿Cómo encontramos al bastardo que lo escribió en primer lugar? – GManNickG

+0

No es una tarea, pero fue un desafío. Después de resolverlo, pensé que no había jugado con J durante mucho tiempo y olvidé su sintaxis. Pensé que algunos aquí lo harían. – Margus

+3

Esta expresión da como resultado un comportamiento indefinido. La subexpresión '((a = ~ x & (~ x >> 1))^= a' hace dos modificaciones no secuenciadas a' a'. La "forma más legible" no da como resultado un comportamiento indefinido, por lo que no es lo mismo cosa. –

Respuesta

5

Sin pruebas, la transcripción básica sería algo como esto:

Shift =: (33 b.) 
And =: (17 b.) 
Not =: (26 b.) 
Xor =: (22 b.) 
Or =: (23 b.) 

BastardFunction =: 3 : 0 
    a =. (Not y) And (_1 Shift (Not y)) 
    if. a do. 
    b =. a Xor (a And a - 1) 
    (1 Shift b) Or b 
    else. 
    0 
    end. 
) 

Pero podría ser un enfoque más inteligente.

+0

Hmmm, no obtengo 0 muy a menudo ... Es decir, nunca. – MPelletier

+0

Validado para los valores 0-9 Obtengo el mismo resultado que la forma simplificada. – MPelletier

+0

(2^31) -3, (2^31) -2 y (2^31) -1 devolverán 0. – MPelletier

3

Aquí está una pequeña analyzis (de la versión "forma legible"):

usnigned int nx = ~x; // I suppose it's unsigned 
int a = nx & (nx >> 1); 
// a will be 0 if there are no 2 consecutive "1" bits. 
// or it will contain "1" in position N1 if nx had "1" in positions N1 and N1 + 1 
if (a == 0) return 0; // we don't have set bits for the following algorithm 
int b = a^(a & (a - 1)); 
// a - 1 : will reset the least 1 bit and will set all zero bits (say, NZ) that were on smaller positions 
// a & (a - 1) : will leave zeroes in all (NZ + 1) LSB bits (because they're only bits that has changed 
// a^(a & (a - 1)) : will cancel the high part, leaving only the smallest bit that was set in a 
// so, for a = 0b0100100 we'll obtain a power of two: b = 0000100 
return b | (b << 1);  
// knowing that b is a power of 2, the result is b + b*2 => b*3 

Parece que el algoritmo está buscando los primeros 2 bits (comenzando desde LSB) 0 consecutivos en la variable x. Si no hay ninguno, entonces el resultado es 0. Si se encuentran, por ejemplo, en la posición PZ, el resultado contendrá dos bits de configuración: PZ y PZ+1.

Cuestiones relacionadas