一つの数の最高のバイナリビットを求めます。(java)

2448 ワード

たとえば、入力:42(0010 1010)   出力:32(0010 0000)
i位が1、1~i-1位が0、i+1~最後のビットが0または1であると仮定して、xを表します。
考え方:
1)0000 0000 0000×01 xxxxは0000 0111 1111になる。
2)0000 0000,0111-1111-0000 0011 1111で、結果=0000 0100 0000
どうやって実現しますか?
私たちはnum=0000 01xx、n=numバイナリの桁数を持っています。既知:1|0=1,1|1=1。i番目は1ですので、i番目の値を後に渡すことができます。num(num>>1)の結果は、i位とi+1位がいずれも1であることを示しています。num(num>>2)の赋価をnumに与える。num(num>>2を継続して実行した結果、i番目、i+1、i+2、i+3位はいずれも1となりました。この類推により、num(num>>4)の賦値をnumに与えた結果、i+1…i+7(i+7<=n)はいずれも1であることが分かりました。num(num>>8)の割当値をnumに与えたところ、i+1…i+15(i+15(=32)はいずれも1であることが分かりました。したがって解決は実現された。
どうやって実現しますか?
num=num-(num>>1)
じゃ、なぜ初めて>>1、第二回>>2、第三回>>4、第四回>>8…?
実現>>1の後に、2人が確定した1があるので、今度は2人を移動したほうが早いです。実現>>2を行うと、4桁の確定があります。
>>>>と>>の違いは何ですか?
1)>>は、シフト後左側の空格子点を最高位のパディングで右にシフトします。
2)>>は論理の右に移動し、左側の空席を0で埋める。
実は1)の中で、>>>や>>を使ってもいいです。2)の中では、必ず>>>>>>>が1位であれば、1)を実現した後、numは111111111111111…であり、num>>1の後は111111111111111111111111111であるから…。2)ステップ終了後、num値は0となります。したがって、必要なのは右に移動する過程で0を補うので、>>
具体的なコードの実現:
public class GetHightBit {
    public static int getHighBit(int num){
        num|=(num>>>1);
        num|=(num>>>2);
        num|=(num>>>4);
        num|=(num>>>8);
        num|=(num>>>16);
        num=num-(num>>>1);
        return num;
    }

    public static void main(String[] args) {
        System.out.println(getHighBit(80));
    }
}
-----------------------------------------------
    :
64
【実は、以上はInteger類のhighestOneBit(int i)の方法です。ここでは分析を行うだけです。】
もう一つの方法があります。
public class GetHightBit2 {
    public static int getHighBit(int num){
        int i;
        for(i=0;num>=2;i++){
            num=num/2;
        }
        return (int)Math.pow(2,i);


    }

    public static void main(String[] args) {
        System.out.println(getHighBit(123));
    }
}
 
まとめ:
1.num=123の場合、2つの方法の1000万回をテストします。ビットで計算する時間:2 ms。モールドで計算する時間:10 ms。
ビット演算を使うと効率が大幅に向上し、コードの最適化が可能になります。
2.除算はビット演算よりも時間がかかるので、ビット演算が早いです。第二の方法はレジスタとメモリの読み書きメモリがありますが、ビット演算は直接レジスタで演算されますので、ビット演算は速いです。
3.自分のコードを効率よく実行するためには、以下の点から着手することができます。
1)できるだけ順番で実行し、循環しないでください。
2)変数をできるだけ少なく使います。
3)できるだけ下の方の演算を多く使います。例えば、ビット演算です。
4)できるだけ少なめに再帰する。再帰コードが少なく、速度が遅い。