/ Forside / Teknologi / Udvikling / Java / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
Java
#NavnPoint
molokyle 3688
Klaudi 855
strarup 740
Forvirret 660
gøgeungen 500
Teil 373
Stouenberg 360
vnc 360
pmbruun 341
10  mccracken 320
Problem med bit rotation i java(ingen unsi~
Fra : m.j


Dato : 10-12-03 14:31

Hej d.e.p.java,

Er der nogen der ved hvordan man kan konvertere denne pascal(delphi),
funktion til java?

Problemet er at den ingen "Longword" er i java,
her ser det kun ud til der er "signed" typer, og ingen "unsigned"?

Det er en funktion der samler 4 bytes i en array(Hvor afhænger af P),
til en "32bit unsigned type".

Her bliver den så bit roteret til højre k antal gange.

Og endelig bliver "32bit unsigned type" splittet op i 4 byte arrays igen.

Men funktioner virker anderledes i java og giver IKKE samme resultat.

Jeg tror problemet ligger i den "miderste" kode.

"B12Ar" er en array af 12 bytes(0..11), kan hver indeholder et tal mellem
0.255
"P" kan være "0" eller "8".
"k" kan være "10" eller "31".

-----------
procedure Cyc32(var Buf: B12Ar;P: byte;k: integer);
var
i : integer;
x,y : Longword;

begin
x := Buf[P];
x := x shl 8;
x := x or Buf[P + 1];
x := x shl 8;
x := x or Buf[P + 2];
x := x shl 8;
x := x or Buf[P + 3];

for i := 1 to k do
begin
// Cyclical Rotate 32 bits word right k times
y := x and 1; // Extract Carry
y := y shl 31; // Move Carry to Msb
x := x shr 1; // Do Shift
x := x or y; // Add Carry
end;

Buf[P + 3] := x;
x := x shr 8;
Buf[P + 2] := x;
x := x shr 8;
Buf[P + 1] := x;
x := x shr 8;
Buf[P] := x;
end;
-----------

Nogle iderer?


Takker på forhånd.


--
Hilsen
M.j.



 
 
Filip Larsen (10-12-2003)
Kommentar
Fra : Filip Larsen


Dato : 10-12-03 23:23

"m.j" skrev

> Er der nogen der ved hvordan man kan konvertere denne pascal(delphi),
> funktion til java?
> [...]
> for i := 1 to k do
> begin
> // Cyclical Rotate 32 bits word right k times
> y := x and 1; // Extract Carry
> y := y shl 31; // Move Carry to Msb
> x := x shr 1; // Do Shift
> x := x or y; // Add Carry
> end;
>

Det burde virke hvis man bruger "unsigned right shift" operatoren (>>>):

int x;
..
for (int i = 0; i < k; i++) {
x = (x >>> 1) | ((x & 1) << 31);
}

Alternativt kan man skifte k gange (0 < k < 32) i stedet for at
itererer:

x = (x >>> k) | (x & ((1 << k) - 1)) << (32-k);

hvor masken ((1<<k)-1) evt. kan lægges i en statisk tabel hvis hastighed
er påkrævet.



Mvh,
--
Filip Larsen



Filip Larsen (11-12-2003)
Kommentar
Fra : Filip Larsen


Dato : 11-12-03 00:12

Jeg skrev

> Alternativt kan man skifte k gange (0 < k < 32) i stedet for at
> itererer:
>
> x = (x >>> k) | (x & ((1 << k) - 1)) << (32-k);
>
> hvor masken ((1<<k)-1) evt. kan lægges i en statisk tabel hvis
hastighed
> er påkrævet.

Jeg var vist ikke helt vågen, for der er faktisk slet ikke brug for
nogen maske og det vil sige, at hele iterationen kan erstattes med

x = (x >>> k) | (x << (32-k))


Mvh,
--
Filip Larsen



m.j (11-12-2003)
Kommentar
Fra : m.j


Dato : 11-12-03 22:00

Hej,

Takker Filip og Peter,
nu har jeg fået det til at køre

Fandt frem til at jeg skulle bruge en long,
da int ik havde plads nok pga af signed bit'ten.
(skulle bruge fra 0x00000000-0xFFFFFFFF)

>at hele iterationen kan erstattes med
>x = (x >>> k) | (x << (32-k))
Prøvede jeg, og gav et bedre resultat,
men tilføjde AND 0x003FFFFF(eller 0x00000001) +nogle AND 0xFF og så virkede
det!!
(Se kode)

>Det burde virke hvis man bruger "unsigned right shift" operatoren (>>>):
Hmm, det ser ik ud til at ha nogen virkning om jeg bruger >> eller >>>.
Skal stadigvæk AND'e med 0x003FFFFF(eller 0x00000001) for at det virker???
Skulle den ik sætte "foran stående" bits til 0??

Hej er koder der virker og giver det samme resultat som pascal routinen:
----------------------------------
public void cyc32( byte[] buf, byte p, byte k )
{
long x;

// Kopier fire int fra buf[p] til og med buf[p+3] ind i x;
x = (buf[p] & 0xff)<<24 | (buf[p+1] & 0xff)<<16 | (buf[p+2] & 0xff)<<8 |
(buf[p+3] & 0xff);

// rotér long x til højre, k antal gange
if (k==10)
x = ( ((x >> k) & 0x003FFFFF) | (x << (32-k)) );
else //if (k==31)
x = ( ((x >> k) & 0x00000001) | (x << (32-k)) );

// Kopier x tilbage til bufferen
buf[p] = (byte)((x >> 24) & 0xff);
buf[p+1] = (byte)((x >> 16) & 0xff);
buf[p+2] = (byte)((x >> 8) & 0xff);
buf[p+3] = (byte)(x & 0xff);
}
----------------------------------

Tak for hjælpen!


--
Hilsen
M.j.



Filip Larsen (12-12-2003)
Kommentar
Fra : Filip Larsen


Dato : 12-12-03 01:43

Jeg skrev

> > x = (x >>> k) | (x << (32-k))

og m.j svarede

> Prøvede jeg, og gav et bedre resultat,
> men tilføjde AND 0x003FFFFF(eller 0x00000001) +nogle AND 0xFF og så
virkede
> det!!

Det kan altså godt gøres med en int og uden de fleste af de masker du
nævner. Masker er kun nødvendige når du danner x da java ellers vil
sign-extende dine bytes.

Følgende har jeg testet virker:

public void cyc32(byte[] buf, int p, int k) {
int x = 0;
for (int i = 0; i < 4; i++) {
x = (x << 8) | (buf[p+i] & 0xFF);
}
x = (x >>> k) | (x << (32-k));
for (int i = 3; i >= 0; i--) {
buf[p+i] = (byte) x;
x >>= 8;
}
}


Mvh,
--
Filip Larsen



m.j (12-12-2003)
Kommentar
Fra : m.j


Dato : 12-12-03 14:10

Hej igen,

> Det kan altså godt gøres med en int og uden de fleste af de masker du
> nævner.
ok
Er nybegynder i java

>Masker er kun nødvendige når du danner x da java ellers vil
>sign-extende dine bytes.
Det forklarer jo det hele...
Troede at hvis man declared "int x;" så blev den automatisk sat til 0,
men det kan jeg se at den ikke gør.

Men forstår stadig ikke helt hvordan det kan lade gøre at bruge en
"signed int", en bit bliver vel brugt til at sætte + eller -?
Og derved "skulle" den ikke kunne indeholder 0x00000000-0xFFFFFFFF
kombinationer,
som en "unsigned Longword" kan(i pascal)??
Men det kan den jo alligevel!, hvad overser jeg?


> Følgende har jeg testet virker:
> public void cyc32(byte[] buf, int p, int k) {
> int x = 0;
> for (int i = 0; i < 4; i++) {
> x = (x << 8) | (buf[p+i] & 0xFF);
> }
> x = (x >>> k) | (x << (32-k));
> for (int i = 3; i >= 0; i--) {
> buf[p+i] = (byte) x;
> x >>= 8;
> }
> }

Ja, det virker helt fint!
(Både med x = int eller long)

--
Hilsen
M.j.



Filip Larsen (12-12-2003)
Kommentar
Fra : Filip Larsen


Dato : 12-12-03 20:19

"m.j" skrev

> Troede at hvis man declared "int x;" så blev den automatisk
> sat til 0, men det kan jeg se at den ikke gør.

Modsat instans-variable der har en naturlig default værdi (0 eller null)
så skal alle lokale variable eksplicit tildeles en værdi før de
refereres første gang. Det nemmeste er som regel at tildele værdien
sammen med deklareringen af variablen, men det er ikke noget krav. Se
evt.

http://java.sun.com/docs/books/jls/second_edition/html/conversions.doc.html#26917
for detaljer omkring dette.


> Men forstår stadig ikke helt hvordan det kan lade gøre at bruge en
> "signed int", en bit bliver vel brugt til at sætte + eller -?
> Og derved "skulle" den ikke kunne indeholder 0x00000000-0xFFFFFFFF
> kombinationer, som en "unsigned Longword" kan(i pascal)??

Som tommelfingerregel kan man regne med at simple heltalstyper altid er
signed. Der er dog en mængde operatorer der virker "ens" uanset om det
underliggende 32-bit tal tolkes som signed eller unsigned. Bitvis "og",
"eller" og "xor" er af den type, og med disse kan man fint "lade som om"
tallet er unsigned. Højre-skift operatoren derimod findes i to
forskellige version fordi den ene laver sign-extension (>>) mens den
anden (>>>) ikke gør.



Mvh,
--
Filip Larsen



m.j (13-12-2003)
Kommentar
Fra : m.j


Dato : 13-12-03 18:15

Filip skrev:

> Modsat instans-variable der har en naturlig default værdi (0 eller null)
> så skal alle lokale variable eksplicit tildeles en værdi før de
> refereres første gang. Det nemmeste er som regel at tildele værdien
> sammen med deklareringen af variablen, men det er ikke noget krav. Se
ok

> Som tommelfingerregel kan man regne med at simple heltalstyper altid er
> signed. Der er dog en mængde operatorer der virker "ens" uanset om det
> underliggende 32-bit tal tolkes som signed eller unsigned. Bitvis "og",
> "eller" og "xor" er af den type, og med disse kan man fint "lade som om"
> tallet er unsigned. Højre-skift operatoren derimod findes i to
> forskellige version fordi den ene laver sign-extension (>>) mens den
> anden (>>>) ikke gør.
Det forklarer jo det hele.

Så lærte jeg også noget idag

Takker for hjælpen, og den gode forklaring!


--
mvh
m.j.



Peter Lind (10-12-2003)
Kommentar
Fra : Peter Lind


Dato : 10-12-03 23:33

m.j wrote:
> Hej d.e.p.java,
>
> Er der nogen der ved hvordan man kan konvertere denne pascal(delphi),
> funktion til java?
> Problemet er at den ingen "Longword" er i java,
> her ser det kun ud til der er "signed" typer, og ingen "unsigned"?

Det er korrekt, men det er for så vidt irrelevant mht bit-rotation. Og der
er iøvrigt en long datatype i java.

> Det er en funktion der samler 4 bytes i en array(Hvor afhænger af P),
> til en "32bit unsigned type".
> Her bliver den så bit roteret til højre k antal gange.
>
> Og endelig bliver "32bit unsigned type" splittet op i 4 byte arrays
> igen.
>
> Men funktioner virker anderledes i java og giver IKKE samme resultat.

Virker bitoperationfunktioner ikke ens i java og pascal? Det lyder sært, men
da du ikke har postet dit java-program, er det svært at sige hvad der kan
være galt.

> Jeg tror problemet ligger i den "miderste" kode.

altså i for-løkken?

> "B12Ar" er en array af 12 bytes(0..11), kan hver indeholder et tal
> mellem
> 0.255
> "P" kan være "0" eller "8".
> "k" kan være "10" eller "31".

jeg oversætter programmet linje for linje - så må du selv prøve om det giver
samme resultat, jeg synes det er lidt svært at gennemskue meningen med det.

public void cyc32( byte[] buf, byte p, int k )
{
int x, y;

// Kopier fire bytes fra buf[p] til og med buf[p+3] ind i x;
x = buf[p]<<24 | buf[p+1]<<16 | buf[p+2]<<8 | buf[p+3];

// rotér int x til højre, k antal gange
for( int i=0; i < k; i++ )
{
// Hvis LSB i x er 1, så sæt MSB i y til 1
y = x & 1;
y = y << 31;
x = x >> 1;
x = x | y;
}

// Kopier x tilbage til bufferen
buf[p] = (byte)((x >> 24)&0xff);
buf[p+1] = (byte)((x >> 16)&0xff);
buf[p+2] = (byte)((x >> 8)&0xff);
buf[p+3] = (byte)(x);

}

Det virker ihvertfald fint her - men husk at hvis du udskriver bytes der er
større ens 0x7f, så bliver de vist som negative tal. Det kan ordnes ved at
typecaste dem til ints i forbindelse med udskrivningen.

System.out.println("buffer0: " + (int)buf[0] + " - buffer1: " +
(int)buf[1] ); // etc.


--
Mvh
Peter Lind



m.j (11-12-2003)
Kommentar
Fra : m.j


Dato : 11-12-03 22:12

Hej,

Takker Filip og Peter,
nu har jeg fået det til at køre

Fandt frem til at jeg skulle bruge en long,
da int ik havde plads nok pga af signed bit'ten.
(skulle bruge fra 0x00000000-0xFFFFFFFF)

Tilføjede også nogle AND 0xFF + noget mere,
og så virkede det!!
(se koden)

>Virker bitoperationfunktioner ikke ens i java og pascal?
Ved det ikke, men cyc32 funktioner gav ihvert ik samme resultat...

>Det lyder sært, men
>da du ikke har postet dit java-program, er det svært at sige hvad der kan
>være galt.
Var lidt for hurtig...

>altså i for-løkken?
Ja

>jeg oversætter programmet linje for linje - så må du selv prøve om det
giver
>samme resultat,
cyc32 funktionen gav ik det samme resultat, når den blev direkte oversat..

>jeg synes det er lidt svært at gennemskue meningen med det.
Funktionen er brugt i en "krypterings" algoritme.

>Det virker ihvertfald fint her - men husk at hvis du udskriver bytes der er
>større ens 0x7f, så bliver de vist som negative tal. Det kan ordnes ved at
>typecaste dem til ints i forbindelse med udskrivningen.
ok, fandt jeg ud af


Hej er koden der virker og giver det samme resultat som pascal routinen:
(Kan sikkeret forbedres/gøres simplere)
----------------------------------
public void cyc32( byte[] buf, byte p, byte k )
{
long x;

// Kopier fire int fra buf[p] til og med buf[p+3] ind i x;
x = (buf[p] & 0xff)<<24 | (buf[p+1] & 0xff)<<16 | (buf[p+2] & 0xff)<<8 |
(buf[p+3] & 0xff);

// rotér long x til højre, k antal gange
if (k==10)
x = ( ((x >> k) & 0x003FFFFF) | (x << (32-k)) );
else //if (k==31)
x = ( ((x >> k) & 0x00000001) | (x << (32-k)) );

// Kopier x tilbage til bufferen
buf[p] = (byte)((x >> 24) & 0xff);
buf[p+1] = (byte)((x >> 16) & 0xff);
buf[p+2] = (byte)((x >> 8) & 0xff);
buf[p+3] = (byte)(x & 0xff);
}
----------------------------------

Tak for hjælpen!

--
Hilsen
M.j.



Søg
Reklame
Statistik
Spørgsmål : 177459
Tips : 31964
Nyheder : 719565
Indlæg : 6408183
Brugere : 218881

Månedens bedste
Årets bedste
Sidste års bedste