找出右移的两个因素

时间:2016-08-09 19:30:46

标签: c# bit-manipulation

社区,

假设我们有一个随机整数,它在Int32.MinValue - Int32.MaxValue范围内。 我想找到两个数字,这些数字在使用右移运算符一起计算时会得到这个整数。

一个例子:

如果输入值为123456,则两个可能的输出值可能是202270310414,因为2022703104 >> 14 == 123456

这是我的尝试:

 private static int[] DetermineShr(int input)
        {
            int[] arr = new int[2];

            if (input == 0)
            {
                arr[0] = 0;
                arr[1] = 0;
                return arr;
            }

            int a = (int)Math.Log(int.MaxValue / Math.Abs(input), 2);
            int b = (int)(input * Math.Pow(2, a));
            arr[0] = a;
            arr[1] = b;
            return arr;
        }

然而,对于某些否定值,它不起作用,输出不会导致正确的计算。

对于非常小的输入值,例如-2147483648,它会抛出异常:

enter image description here

如何修改我的功能,以便为Int32.MinValueInt32.MaxValue之间的所有输入值生成有效输出?

1 个答案:

答案 0 :(得分:2)

好吧,让我们进行比较

     123456     == 11110001001000000
  ‭   2022703104 == 1111000100100000000000000000000‬
你能看到这种模式吗?如果您已获得shift(在您的情况下为14)答案是

 (123456 << shift) + any number in [0..2 ** (shift-1)] range 

但是,对于大值左移,可能会导致整数溢出;如果shift很小(小于32)我建议使用long

  private static long Factor(int source, int shift) {
    unchecked {
      // (uint): we want bits, not two complement
      long value = (uint) source;

      return value << shift;
    }
  }

测试:

   int a = -1;
   long b = Factor(-1, 3);

   Console.WriteLine(a);
   Console.WriteLine(Convert.ToString(a, 2));
   Console.WriteLine(b);
   Console.WriteLine(Convert.ToString(b, 2)) 

将返回

   -1
   ‭11111111111111111111111111111111
   34359738360
   ‭11111111111111111111111111111111000‬

请注意,否定整数是两个补充

https://en.wikipedia.org/wiki/Two%27s_complement

事实上,

在被视为 unsigned 整数

时非常大