2

最近我问了一个问题:Replace byte in a int

这显示了如何替换整数上的字节。我也需要对 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变量执行了隐式转换),则移位计数由第二个操作数的低五位给出。在这种情况下,因为shiftBits等于 32 = 2^5,在二进制表示中是 100000,所以低五位是 00000。

除了显式强制转换 ( (long)0xFF) 之外,您还可以在常量后面加上 anl或 anL以将它们标记为long/ Int64(或ul/UL表示ulong/ UInt64),但0xFFL某些人可能会认为它们不那么美观/可读。对于这种replaceByte << shiftBits情况,需要显式强制转换。

于 2012-10-31T16:42:57.133 回答
1

您需要将常量0xff转换为long

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

如果你不这样做并且index大于 3 那么mask将有错误的值,因为文字0xff是 anint并且还有这个规则

如果第一个操作数是 int 或 uint(32 位数量),则移位计数由第二个操作数的低五位给出。即,实际移位计数为 0 到 31 位。

由于在这种情况下,移位计数是 2 的幂并且大于 31,它的低五位将全部为零,这将导致根本没有移位(好像shiftBits == 0)。所以mask会有错误的值,它会清除错误的位value,产生错误的结果。

于 2012-10-31T16:32:59.933 回答
0

替换0xFF << ( index * 8 )(long)0xFF << ( index * 8 )

于 2012-10-31T16:35:04.023 回答