2012-03-08 16 views
9

Tengo un comportamiento extraño Me preguntaba si alguien podría aclararme.Negación del maleficio en PHP, comportamiento divertido

Check it out

$hex = 0x80008000; 

print_r(decbin(intval($hex)) . '<br/>'); 
print_r(decbin($hex)); 

salidas

10000000000000001000000000000000 
10000000000000001000000000000000 

Tal como se esperaba.

Pero

$hex = 0x80008000; 

print_r(decbin(~intval($hex)) . '<br/>'); 
print_r(decbin(~$hex)); 

salidas

1111111111111110111111111111111 
1111111111111111111111111111111 

¿Por qué es el bit medio de conmutación cuando no $hex es negado?

+0

¿Qué versión de PHP estás usando? El segundo caso funciona para mí en 5.3.6 –

+0

Estoy ejecutando 5.3.8 y el problema existe. – Pateman

+0

Estoy usando 5.2.17 – Vigrond

Respuesta

0

Va a dar una oportunidad a mi propia pregunta aquí.

Sí, esto es una diferencia de 32 bits/64 bits.

En los sistemas de 32 bits, un tipo flotante tiene que ocupar dos espacios de memoria para obtener los 64 bits necesarios. Php usa doble precisión (vea http://en.wikipedia.org/wiki/Floating_point#IEEE_754:_floating_point_in_modern_computers)

El $ hex se evalúa como un tipo de letra flotante. Las funciones intval y decbin lo convierten en un tipo int (primer ejemplo anterior)

En el segundo ejemplo estamos utilizando el operador no bit a bit ANTES de usar decbin. Esto invierte primero los bits en el flotador de precisión doble del espacio de dos memorias, y luego se convierte en segundo int.Dándonos algo diferente de lo que esperábamos.

De hecho, si ponemos la negate interior de la intval(), así:

$hex = 0x80008000; 

print_r(decbin(intval(~$hex)) . '<br/>'); 
print_r(decbin(~$hex)); 

Obtenemos

1111111111111111111111111111111 
1111111111111111111111111111111 

como salida.

No soy lo suficientemente bueno como para probar esto con las matemáticas todavía (que se puede deducir con la ayuda de este artículo http://en.wikipedia.org/wiki/Double_precision). Pero tal vez cuando tenga tiempo más tarde -_-

Creo que es muy importante aprender cómo se representan los números en las computadoras para que podamos entender anomalías como esta y no llamarlas fallas.

-1

Posiblemente el caso previsto en esto:

Desde la página php operadores bit a bit http://us3.php.net/manual/en/language.operators.bitwise.php

El NO o complemento del operador (~) y números binarios negativos pueden ser confuso.

~ 2 = -3 porque utiliza la fórmula ~ x = -x - 1 El complemento bit a bit de un número decimal es la negación del número menos 1.

NOTA: sólo usar 4 bits aquí para los ejemplos a continuación pero en realidad PHP usa 32 bits.

la conversión de un número decimal negativo (es decir: -3) en binario toma 3 pasos: 1) convertir la versión positiva del número decimal en binario (es decir: 3 = 0,011) 2) voltea los bits (es decir: 0011 se convierte en 1100) 3) agregue 1 (es decir: 1100 + 0001 = 1101)

Usted se estará preguntando cómo funciona 1101 = -3. Bueno PHP usa el método "complemento de 2" para representar números binarios negativos. Si el bit más a la izquierda es un 1, entonces el número binario es negativo y voltea los bits y agrega 1. Si es 0, entonces es positivo y no tiene que hacer nada. Entonces 0010 sería un positivo 2. Si es 1101, es negativo y voltea los bits para obtener 0010. Agregue 1 y obtenga 0011 que es igual a -3.

+0

No creo que esté relacionado con la pregunta. Desde mi entendimiento, 'intval ($ hex)' debería ser exactamente equivalente a '$ hex', por lo que esperaría' ~ intval ($ hex) === ~ $ hex'. –

+0

Sí, no estoy convirtiendo nada aquí, solo representando números en formato binario. – Vigrond

Cuestiones relacionadas