64 bit logisk operation

Tags:    php 64-bit

Hej

Jeg har et problem med en logisk AND-operation hvor der er tale om to 42 (64) bit tal.

Når jeg "laver" det første tal sourceEnc så går det godt:

for ($i=0;$i<8;$i++)
$sourceEnc=$sourceEnc*38+strpos($validChars,$message[$i]);
...

Dernæst skal leg så lave en AND-operation med en konstant 0x20000000000 men det virker ikke:

if (($sourceEnc & 0x20000000000) != 0)
...

Kun hvis jeg reducerer 0x20000000000 til 0x20000000 (32 bits var) virker det. Jeg har også prøvet at anvende en variabel i stedet for det faste tal men det gør ingen forskel.

Hvad skal jeg gøre for at få det til at virke direkte? Jeg kan sikkert arbejde fra neden af, dvs. AND med 1, men det er umiddelbart mere besværligt vil jeg mene.

/Mik



Indlæg senest redigeret d. 27.12.2012 10:46 af Bruger #4912
8 svar postet i denne tråd vises herunder
1 indlæg har modtaget i alt 1 karma
Sorter efter stemmer Sorter efter dato
Men alligevel kan jeg åbenbart godt multiplicere mig frem til en 64 bit variabel i sourceEnc.

Hvordan tjekker du at det faktisk er en 64 bit integer variabel? Kan det være en double og ikke en integer?

Nu roder jeg ikke med PHP, men det er vidst nok bygget på C eller C++ og PHP's standard int er nok en signed standard int. C/C++'es standard int kan være helt ned til 16 bit signed (-32767 - +32767) og man bør nok finde en anden måde at håndtere tallet på hvis det skal være 100% portabelt.. Men man kan nok være pragmatisk og antage 32 bit, men så har du stadig problemet.

Du siger du ikke kan bruge gmp så jeg lavede lidt googling og fandt denne SO post:
http://stackoverflow.com/a/11076808

Som henviser til:
http://phpseclib.sourceforge.net/math/intro.html

Som er en klasse til PHP til store tal, og den har bit-operationer. Den bruger GMP hvis det er til stede, ellers BCmath, ellers dens egen (langsomme) implementation. Jeg har ikke kigget på det, men det lyder som om fra SO indlægget at du kan pille den ud fra phpseclib.


Edit:
Integer overflow

If PHP encounters a number beyond the bounds of the integer type, it will be interpreted as a float instead. Also, an operation which results in a number beyond the bounds of the integer type will return a float instead.





Indlæg senest redigeret d. 30.12.2012 23:13 af Bruger #14645
Det er ikke det samme tal.

0x20000000000 = 2199023255552 (dec.)
0x20000000 = 536870912 (dec.)

I hexadecimale systemer, prefixer man med 0. Det du gør nu, svarer til at gange tallet med 16 for hvert ekstra nul du sætter ind:

0x20000000 * 16 * 16 * 16 = 0x20000000000

I binær regner man med "implicitte" nuller foran værdien, eller rettere, man ignorere alle nuller foran det første betydende ciffer (det første 1 tal) derfor:

010 = 10
0000010 = 10
osv.

Derfor når du laver en binær AND operation mellem to tal af ulig bitlængde, forstår compileren/CPU'en/whatever det som om at der står nuller. Derfor, eks:

Fold kodeboks ind/udKode 


Læg mærke til at dit 42 bit tal (0x20000000000) bliver prefixet med 64-42 = 22 nuller. Og dit 30 bit tal (0x20000000) bliver prefixet med 64-30 = 34 nuller.



Indlæg senest redigeret d. 27.12.2012 14:20 af Bruger #11328
Hej

Jeg er helt med på at det 42 bits tal 0x20000000000 (i en 64 bit var) ikke er det samme som 0x20000000 (i en 32 bit var).

Det var for at illustrere at den logiske ADN-operation går godt med en 32 bit variabel men ikke med en 64 bit variabel. Så mit webhotel går godt når der laves en logisk and med 32 bit men ikke 64 bit. Men alligevel kan jeg åbenbart godt multiplicere mig frem til en 64 bit variabel i sourceEnc.

sourceEnc er på 42 bit på samme vis som 0x20000000000 er 42 bits.

/Mik



"Går godt"?



Hej Jakob

Med "går godt" mener jeg, at en 32 bit AND operation giver det resultat, på mit webhotel - one.com, som det skal. Det var for at om en AND operation med et stort tal i det hele taget fungerede.

Værdien af sourceEnc fremkommer ved at omsætte en tekststreng til en kombineret numerisk værdi og til det formål kommer alle 42 bit i brug. Så sourceEnc kan kun være i en 64 bit variabel. Den værdi som sourceEnc får er korrekt og den kan IKKE være i en 32 bit variabel. Så sourceEnc er med sikkerhed en 64 bit variabel.

phpinfo for one.com: http://www.one-docs.com/php5/ Hvis jeg checker PHP_INT_MAX så kan jeg se, at det er 32 bit.

Jeg har også prøvet at se om gmp_and ville fungere men gmp er slet ikke installeret. Så det trick kunne jeg heller ikke bruge.

Så på den ene side siger web hotellet at det er et 32 bit PHP, på den anden side kan jeg få den korrekte værdi, der kun kan være i en 64 bit variabel. Men jeg kan ikke lave en logisk AND af to 64 bit variable (reelt anvendes kun de 42 bit).

/Mik



Hej

Hmmm, du er inde på noget. Jeg har prøvet at udskrive bittene i sourcEnc og det ser ud som om det først fra det 35. bit der er forskel på det enkelte udskrevne bit og det det burde være. Men 35 bit er helt skørt.

Jeg har kikke lidt på phpseclib og måske kan jeg sakse noget kode ud fra det. En anden mulighed er, at jeg laver sourceEnc i to 32 bit variable i stedet. Det er noget mere kluntet men muligt.

Jeg har også prøvet, at se om man kunne lave noget typecasting i PHP men det havde jeg heller ikke held med.

Godt nytår
/Mik

Hej

"Mit" problem er løst nu. Jeg var på et 32 bit server på mit webhotel og er nu blevet skiftet til en 64 bit server.

Tak for hjælpen.

/Mik



Indlæg senest redigeret d. 03.01.2013 11:54 af Bruger #4912


Hej

"Mit" problem er løst nu. Jeg var på et 32 bit server på mit webhotel og er nu blevet skiftet til en 64 bit server.

Tak for hjælpen.

/Mik

Havde ikke set du havde rettet svaret.

Jeg vil nu ikke kalde det en løsning, men en workaround. Hvad sker der den dag du har brug for 65 bits? Men godt du fik det til at virke.



Indlæg senest redigeret d. 07.01.2013 14:36 af Bruger #14645
Hej Søren

Ja jeg blev "tvunget" til at redigere i mit indlæg. Jeg kunne ikke skrive et nyt da jeg var sidste i listen. Faktisk ville jeg lukke tråden men den "nye" Udvikler kan man ikke længere det. Jeg bruger ikke Udvikleren så tit så har i alle fald ikke kunne finde "luk" som i den "gamle."

Du har ret i den dag jeg har behov for at anvende 65 bits eller mere. Hvis det umiddelbart var et behov ville jeg anvende et andet princip i først instans. I stedet for X=30X+Y ville jeg anvende en opsplitning. Alternativt anvende to 64 bit variable på samme måde som når nogle anvender 2 stk 32 bit variable. I min konkrete situation var det dog nemmere med en enkelt 64 bit variable da specifikationen og C++ koden er lavet sådan.

Dog står jeg ikke lige foran at skulle opgradere til 65 bit i stedet for 42 bit. Anvendelsen er til et digitalt signaleringssystem i luften hvor beskeden først omsættes fra karakterer til en 42 bit værdi. Dernæst noget FEC-foldning (K=32, r=1/2), interleaving og til sidst en statisk vektor før de endelige symboler haves. Alt dette er ret "stift" så det ændrer sig ikke lige med det samme.

Men tak for hjælpen. Jeg kom på rette spor og fik løst problemet.

/Mik



Indlæg senest redigeret d. 07.01.2013 15:53 af Bruger #4912
t