2016-08-09 2 views
1

コミュニティ、右シフトの2つの要因を見つける

範囲はInt32.MinValue - Int32.MaxValueの範囲であるとします。 右のシフト演算子を使って一緒に計算したときに、この整数になる2つの数を見つけたいと思います。

例:いくつかのnegativ値に対するただし

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; 
     } 

入力値がここ2022703104 >> 14 == 123456

は私の試みですので123456 2の可能な出力値は、202270310414可能性がある場合それが機能しない場合、出力は正しい計算にはなりません。

そして、このような-2147483648のような非常に小さな入力値の例外を投げる:

enter image description here

それはInt32.MinValueInt32.MaxValueの間のすべての入力値の有効な出力を生成しますので、どのように私は私の機能を変更することができますか?

+2

として処理した場合、あなたはあまりに2147483648でオーバーフローを取得する必要があります... –

+0

あなたは何を「2の補数」の手段を研究しているしていますか? –

答えて

2

さて、

 123456  == 11110001001000000 
    ‭ 2022703104 == 1111000100100000000000000000000‬ 

を比較してみましょうあなたはパターンを見ることができますか?あなたは(あなたのケースで14shiftを与えられている場合答えは整数オーバーフローにつながることができます左シフト大きな値に、しかし

(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‬ 

をしてください返し、予告ます2の補完物

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

、実際には、かなり大きな符号なし整数

関連する問題