2012-03-08 22 views
9

Ho qualche strano comportamento Mi chiedevo se qualcuno potesse chiarirmi.Negazione di esadecimale in PHP, comportamento divertente

Check it out

$hex = 0x80008000; 

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

uscite

10000000000000001000000000000000 
10000000000000001000000000000000 

come previsto.

Ma

$hex = 0x80008000; 

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

uscite

1111111111111110111111111111111 
1111111111111111111111111111111 

Perché il bit di mezzo non il passaggio quando $hex è negata?

+0

Quale versione di PHP stai usando? Il secondo caso funziona per me su 5.3.6 –

+0

Sto eseguendo 5.3.8 e il problema esiste. – Pateman

+0

Sto usando 5.2.17 – Vigrond

risposta

0

Fare uno scatto alla mia domanda qui.

Sì, questa è una differenza a 32 bit/64 bit.

Nei sistemi a 32 bit, un tipo mobile deve occupare due spazi di memoria per ottenere i 64 bit richiesti. Php usa la doppia precisione (vedere http://en.wikipedia.org/wiki/Floating_point#IEEE_754:_floating_point_in_modern_computers)

$ hex viene valutato in un tipo float. Le funzioni intval e decbin convertono questo in un tipo int (1 ° esempio sopra)

Nel 2 ° esempio si utilizza l'operatore non bit a bit PRIMA di utilizzare decbin. Ciò capovolge prima i bit nello spazio a doppia precisione di due spazi di memoria e quindi viene convertito in secondi int.Dandoci qualcosa di diverso da quello che ci aspettavamo.

Infatti, se mettiamo la negate all'interno del intval() in questo modo:

$hex = 0x80008000; 

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

Otteniamo

1111111111111111111111111111111 
1111111111111111111111111111111 

come output.

Non sono abbastanza bravo da provarlo con la matematica (che può essere scoperto con l'aiuto di questo articolo http://en.wikipedia.org/wiki/Double_precision). Ma forse quando avrò tempo dopo -_-

Penso che sia molto importante imparare come i numeri sono rappresentati nei computer in modo che possiamo capire anomalie come questa e non chiamarle bug.

-1

Forse un caso previsto dal presente:

Dalla pagina operatori bit a bit php http://us3.php.net/manual/en/language.operators.bitwise.php

Il NOT o complementare operatore (~) e numeri binari negativi possono essere fonte di confusione.

~ 2 = -3 perché si utilizza la formula ~ x = -x - 1 Il complemento bit a bit di un numero decimale è la negazione del numero meno 1.

NOTA: usando solo 4 bit qui per gli esempi di seguito ma in realtà PHP utilizza 32 bit.

Conversione di un numero decimale negativo (cioè: -3) in binario dura 3 passi: 1) convertire la versione positiva del numero decimale in binario (es: 3 = 0011) 2) inverte i bit (cioè: 0011 diventa 1100) 3) aggiungi 1 (es: 1100 + 0001 = 1101)

Ci si potrebbe chiedere come funziona 1101 = -3. Bene PHP usa il metodo "complemento a 2" per rendere numeri binari negativi. Se il numero più a sinistra di è 1, il numero binario è negativo e si invertono i bit e si aggiunge 1. Se è 0, allora è positivo e non è necessario eseguire . Quindi 0010 sarebbe un positivo 2. Se è 1101, è negativo e si capovolge i bit per ottenere 0010. Aggiungere 1 e si ottiene 0011 che equivale a -3.

+0

Non penso sia collegato alla domanda. Da quanto ho capito, 'intval ($ hex)' dovrebbe essere esattamente equivalente a '$ hex', quindi mi aspetterei' ~ intval ($ hex) === ~ $ hex'. –

+0

Sì, non sto convertendo nulla qui, solo rappresentando i numeri in formato binario. – Vigrond