Laden...

Shifting von UInt32 / ShiftingHelper

Erstellt von ProjectTeamHTLW16 vor 16 Jahren Letzter Beitrag vor 16 Jahren 3.782 Views
P
ProjectTeamHTLW16 Themenstarter:in
3 Beiträge seit 2007
vor 16 Jahren
Shifting von UInt32 / ShiftingHelper

Hi Leute,
habe einen Fehler entdeckt, gelöst und dachte mir, es wäre cool anderen Programmieren die einen ähnlichen Fehler hatten, bzw. um einfach alle davor zu warnen, dass sie nicht in die Falle gehen, es hier einmal zu posten.

Ich habe eine Methode programmiert, die eine Rotation durchführt:


     private UInt16 rotateLeft(UInt16 value, int positions)
        {
            positions = positions % 16;
            UInt16 helper1 = value, helper2 = value;

            helper1 = (UInt16)(helper1 << positions);
            helper2 = (UInt16)(helper2 >> (16-positions));

            return (Convert.ToUInt16(helper1 + helper2));   
        }


        private UInt32 rotateLeft(UInt32 value, int positions)
        {
            positions = positions % 32;
            UInt32 helper1 = value, helper2 = value;

            helper1 = (UInt32)(helper1 << positions);
            helper2 = (UInt32)(helper2 >> (32 - positions));

            return (Convert.ToUInt32(helper1 + helper2));
        } 

Interessanter weise funktioniert diese Methode für ein Shifting von 0 bei der 16-Bit variante, jedoch nicht bei der 32-Bit variante. Warum?
Ich weiß es nicht, aber aus irgendeinem Grund funktioniert bei positions=0 bei der 16-Bit Variante das zweite Shifting vollkommen (sprich der Wert wird auf 0 gesetzt -> klar, er wird ja aus dem Wertebereich rausgeschoben);
Aber bei der 32-Bit Variante wird diese Funktion einfach ignoriert:

helper2 = (UInt32)(helper2 >> 32);

Ich weiß nicht warum er das so macht, aber als Lösung fügt man einfach folgende Zeile hinzu, die bei 0 direkt den eingegebenen Wert zurückliefert.
Sprich die Methoden sehen dann so aus:


     private UInt16 rotateLeft(UInt16 value, int positions)
        {
            if(positions==0)
                 return value;
            positions = positions % 16;
            UInt16 helper1 = value, helper2 = value;

            helper1 = (UInt16)(helper1 << positions);
            helper2 = (UInt16)(helper2 >> (16-positions));

            return (Convert.ToUInt16(helper1 + helper2));   
        }


        private UInt32 rotateLeft(UInt32 value, int positions)
        {
            if(positions==0)
                 return value;
            positions = positions % 32;
            UInt32 helper1 = value, helper2 = value;

            helper1 = (UInt32)(helper1 << positions);
            helper2 = (UInt32)(helper2 >> (32 - positions));

            return (Convert.ToUInt32(helper1 + helper2));
        } 

Liebe Grüße
Alex

S
8.746 Beiträge seit 2005
vor 16 Jahren

Aber bei der 32-Bit Variante wird diese Funktion einfach ignoriert:

helper2 = (UInt32)(helper2 >> 32);  

Zitat aus der Hilfe:

If the first operand is an int or uint (32-bit quantity), the shift count is given

by the low-order five bits
of the second operand (second operand & 0x1f).

Der maximale Wert ist also 31.

So richtig erschließt sich mir der Sinn deiner Funktionen aber nicht. Einer der beiden Summanden (helper1/2) wird immer zu Null. Warum nicht einfach

wert << position // bzw. >>
U
1.688 Beiträge seit 2007
vor 16 Jahren

So richtig erschließt sich mir der Sinn deiner Funktionen aber nicht. Einer der beiden Summanden (helper1/2) wird immer zu Null.

Ziel ist eine "Rotation", d.h. Bits, die links oder rechts herausgeschoben werden, erscheinen auf der anderen Seite wieder. So ergibt z. B.
UInt16 t = rotateLeft(0xC000, 1);
t=0x8001

S
8.746 Beiträge seit 2005
vor 16 Jahren

Ah ja. Dann würde ich allerdings ver-odern (statt zu addieren). Macht den Sinn klarer.

U
1.688 Beiträge seit 2007
vor 16 Jahren

Ja. Auch %16 bzw. %32 sollten eher durch bit-& ersetzt werden.

Das Problem mit dem Verschieben um 32 Stellen kann man übrigens lösen, wenn man temporär mit long-Variablen arbeitet.