Jump to content
php.lv forumi

Bitisko aprēķinu nesakritības uz serveriem


Kaitnieks

Recommended Posts

Šāds kods:

 

<?


$c = 1265440854;
$e = -2291984452;
$Xl = ($e ^ $c);

echo $Xl;
?>

 

Uz lokālā Windows servera atgriež: 1007554538

Uz linux atgriež: -882042794

 

Bitos:

0000000000000000000000000000000001001011011011010001100001010110 = $c XOR

1111111111111111111111111111111101110111011000110001011110111100 = $e

0000000000000000000000000000000000111100000011100000111111101010 = winres

1111111111111111111111111111111111001011011011010001100001010110 = linres

 

Skaidri redzams, ka linuksiskais serveris kljuudaas jau pie 3. bita.

 

Es esmu konkrēti apstulbis, varbūt kāds var apgaismot? Paldies.

Link to comment
Share on other sites

Nezinu kā tev, bet man linuxis (PHP 5.2.3) atgrieza: -3287412758

Izskatās, ka tas skaitļus rēķina 64-bitīgos mainīgajos, jo pārvēršot šo skaitli uz bitiem, iegūst:

1111111111111111111111111111111100111100000011100000111111101010

Pareizais rezultāts parakstīts apakšā:

 

1111111111111111111111111111111100111100000011100000111111101010
							00111100000011100000111111101010
							|
							\-- 32-tais bits

 

Un man ir aizdoma, ka Windows printf's, kas iekompilēts php kodā, nemāk izdrukāt signed long long. tāpēc šis drukā signed long, kas ir 32-bitīga vērtība.

 

Edit: ai šit, aizmirsu, ka man linuxis 64-bitīgs :) Tātad nevar salīdzināt, jo tam integeri ir 64-bitīgi, taču windowsam 32. Papētīšu labāk php sourci.

Link to comment
Share on other sites

Ka tik vaina nav tur, ka skaitlis -2291984452 nevar eksistēt 32-bitos. Jo max negatīvais skaitlis, ko var attēlot 32-bitos ir -2147483648. Notiek kautkāds jokains overflows, kuru viens interpretē vienā veidā, otrs citā.

Link to comment
Share on other sites

Nuja, bubu, pareizi, tādu rezultātu es arī gaidītu 64 bitu vērtībām (piezīme sev: jāiegaumē, ka šis kods uz 64 bitu kastēm sagādās problēmas, paldies, bubu).

 

Vispār tas algoritms izmaļ cauri ļoti daudz dažādas vērtības, pirms nokļūdās pie šiem skaitļiem. Mums te ir tāds termins: miracle...

Link to comment
Share on other sites

Ka tik vaina nav tur, ka skaitlis -2291984452 nevar eksistēt 32-bitos. Jo max negatīvais skaitlis, ko var attēlot 32-bitos ir -2147483648. Notiek kautkāds jokains overflows, kuru viens interpretē vienā veidā, otrs citā.

 

Ok, šitais ir labs pavediens, papētīšu sīkāk.

Link to comment
Share on other sites

hehe, uz windas:

<?php
 $a = -2291984452;

 echo is_float($a) ? "float" : "no", "\n";
?>

izdrukāja "float".

ej un definē operāciju xor starp float un integer :)

 

Secinājums: PHP ar weak-typing nerullz, Python ar savu strongly-typed mainīgajiem rullz.

Link to comment
Share on other sites

PHP pie bitiskaam operaacijaam dazjaadi uzvedas uz dazjadiem Prochiem (pat nav seviskjas atskjiriibas par OP sisteemu ...)

uz 64 bitiiggajiem dzelzjiem buus cits rezultaat uz 32 cits.... Netaa ir diezgan daudz infas tieshi par sho temu....

Link to comment
Share on other sites

Tam nu gan es neticu.

kam tieshi?

ka saistiiba ir ar proci?

Esmu parliecinaajies ka uz kastes ar 64 bit dzlzjiem stav tas pats Win un tiek veikti kljuudaini aprekjini :(

HVZ kapeec bet nu ir bijushi gadijumi..... (itkaa reaala izskaidrojuma pat iisti nav....)

Link to comment
Share on other sites

jep, tieši ar proci.

Bet 64-bit vs 32-bit dzelzi ir izskaidrot vienkārši - tur integeri ir 64-bitīgi un operācijas, kurās rezultāts ir lielāks par 2^31-1, dos atšķirīgu rezultātu no 32-bitos darbinātas operācijas. Tā jau gan nav php vaina, tas pats būtu arī C/C++ valodās, ja par integer mainīgo ņemtu tipu long. Tā ir algoritma kļūda, ka balstās uz tādiem pieņēmumiem. T.i. tas nav 64-bitu drošs kods. C/C++ valodās papildus šim vēl būtu problēmas ar pointeriem, jo tos nedrīkstētu piešķirt int mainīgajiem.

Vienīgais php sliktums, ko augstāk minēju ar maziem burtiem, ir tas, ka php ir weak-typed valoda, tas automātiski 32-bitīgu intu nokonvertēs uz double tipu neko nepabrīdinot, ja tas līdīs ārpus diapazona. Un ar to bitwise operācijas veikt nav prātīgi (jo nav definēts).

Link to comment
Share on other sites

v3rb0: Ar to typecast ir jābūt uzmanīgam, jo rezultāts ir šāds:

 

<?php
var_dump((int)-2291984452);
?>

 

int(-2147483648)

 

Tb. ja skaitlis ir ārpus (int) robežām, tad arī typecasts tur nelīdzēs. Gaidam PHP6 ar 64bit integeriem ;)

Link to comment
Share on other sites

×
×
  • Create New...