2

最近私は質問をしました: int の byte を置き換えます

これは、整数のバイトを置き換える方法を示しています。Int64 でも同じことをする必要があります。どうやら私はこれが苦手らしい笑。int を Int64 に置き換えても機能しない理由がわかりません。つまり、最後の質問の解決策を次のように変更しました。

static Int64 ReplaceByte1( int index , Int64 value , byte replaceByte )
{
    return ( value & ~( 0xFF << ( index * 8 ) ) ) | ( replaceByte << ( index * 8 ) );
}

static Int64 ReplaceByte2( int index , Int64 value , byte replaceByte )
{
    // how many bits you should shift replaceByte to bring it "in position"
    var shiftBits = 8 * index;

    // bitwise AND this with value to clear the bits that should become replaceByte
    Int64 mask = ~( 0xff << shiftBits );

    // clear those bits and then set them to whatever replaceByte is
    return value & mask | ( replaceByte << shiftBits );
}

大きな値を使用する場合は機能しません。たとえば、次のようにメソッドを呼び出します。

        // returns 12345678848  where it should return 3755744309
        var test1 = ReplaceByte1( 4 , 12345678901 , 0 );

        // returns 12345678848  where it should return 3755744309
        var test2 = ReplaceByte2( 4 , 12345678901 , 0 );

Int64でも動作させるにはどうすればよいですか? 私は何を間違っていますか?機能する唯一の方法は、最後の最も遅い方法です。

編集

すでに交換を行っていますが、それでも異なる結果が得られます。なんで?見てください:

    // method that words
    static Int64 SlowReplace ( int index , Int64 value , byte replaceByte )
    {
        var bytes = BitConverter.GetBytes( value );
        bytes[ index ] = replaceByte;

        return BitConverter.ToInt64( bytes , 0 );
    }

    static Int64 ReplaceByte1 ( int index , Int64 value , byte replaceByte )
    {
        return ( value & ~( (long)0xFF << ( index * 8 ) ) ) | ( replaceByte << ( index * 8 ) );
    }

    static Int64 ReplaceByte2 ( int index , Int64 value , byte replaceByte )
    {
        // how many bits you should shift replaceByte to bring it "in position"
        var shiftBits = 8 * index;

        // bitwise AND this with value to clear the bits that should become replaceByte
        Int64 mask = ~( ( Int64 )0xff << shiftBits );

        // clear those bits and then set them to whatever replaceByte is
        return value & mask | ( replaceByte << shiftBits );
    }        

    static void Main ( string[ ] args )
    {
        var a = SlowReplace( 4 , 12345678901 , 255 ); //  1098972404789 corect
        var b = ReplaceByte1( 4 , 12345678901 , 255 ); // 3755744511 incorrect
        var c = ReplaceByte2( 4 , 12345678901 , 255 ); // 3755744511 incorrect            

        Console.Read( );            
    }
4

3 に答える 3

2

問題は式に依存していreplaceByte << shiftBitsます。<< Operator ドキュメントを参照してください。

ドキュメントには、最初のオペランドが 32 ビットの量である場合 (この場合は、byte変数に対して暗黙的なキャストが実行されるため)、シフト カウントは 2 番目のオペランドの下位 5 ビットによって与えられると記載されています。この場合、shiftBitsは 32 = 2^5 に等しいため、2 進表現では 100000 であるため、下位 5 ビットは 00000 です。

明示的なキャスト ( ) とは別に、(long)0xFF定数の末尾にlまたはを付けて/ (または/の場合は/ )Lとしてマークすることもできますが、美的/読みにくいと考える人もいます。この状況では、明示的なキャストが必要です。longInt64ulULulongUInt640xFFLreplaceByte << shiftBits

于 2012-10-31T16:42:57.133 に答える
1

0xff定数をlong次のようにキャストする必要があります。

Int64 mask = ~( (Int64)0xff << shiftBits );

これを行わずにindex3 より大きい場合は、リテラルが anであり、次のルールも存在するmaskため、間違った値になります。0xffint

第 1 オペランドが int または uint (32 ビット量) の場合、シフト カウントは第 2 オペランドの下位 5 ビットによって与えられます。つまり、実際のシフト カウントは 0 ~ 31 ビットです。

この場合、シフト カウントは 2 のべき乗であり、31 より大きいため、下位 5 ビットはすべてゼロになり、シフトはまったく発生しません (あたかも のようにshiftBits == 0)。したがってmask、間違った値になり、間違ったビットが からクリアされ、value間違った結果が生成されます。

于 2012-10-31T16:32:59.933 に答える
0

に置き換え0xFF << ( index * 8 )ます(long)0xFF << ( index * 8 )

于 2012-10-31T16:35:04.023 に答える