このソリューションは、元は 2 進数であり、要求者が指定したように従来の数学に変換されました。
少なくとも 2 による乗算と 2 による除算は、速度のために << 1 および >> 1 である必要があります。加算と減算は、おそらくいずれにせよ重要ではありません。
nBits の代わりに mask を渡し、乗算または除算の代わりにビットシフトを使用し、末尾再帰をループに変更すると、他のすべての呼び出しは単一の呼び出しにすぎないため、これがおそらく最もパフォーマンスの高いソリューションになります。追加すると、Alnitak のソリューションと同じくらい遅くなるだけで、4 回、場合によっては 8 回の呼び出しに 1 回しかかかりません。
int incrementBizarre(int initial, int nBits)
// in the 3 bit example, this should create 100
mask=2^(nBits-1)
// This should only return true if the first (least significant) bit is not set
// if initial is 011 and mask is 100
// 3 4, bit is not set
if(initial < mask)
// If it was not, just set it and bail.
return initial+ mask // 011 (3) + 100 (4) = 111 (7)
else
// it was set, are we at the most significant bit yet?
// mask 100 (4) / 2 = 010 (2), 001/2 = 0 indicating overflow
if(mask / 2) > 0
// No, we were't, so unset it (initial-mask) and increment the next bit
return incrementBizarre(initial - mask, mask/2)
else
// Whoops we were at the most significant bit. Error condition
throw new OverflowedMyBitsException()
うわー、それはちょっとクールになりました。私は最後の1秒まで再帰を理解していませんでした。
それは間違っているように感じます-動作しないはずの操作がいくつかあるように感じますが、あなたがしていることの性質のために動作します(少し左にいくつかのビットを操作しているときに問題が発生する必要があるように感じます)はゼロではありませんが、左側のすべてのビットがゼロでない限り、ビットを操作することはできません。これは非常に奇妙な条件ですが、本当です。
110 から 001 に取得するフローの例 (後方 3 から後方 4):
mask 100 (4), initial 110 (6); initial < mask=false; initial-mask = 010 (2), now try on the next bit
mask 010 (2), initial 010 (2); initial < mask=false; initial-mask = 000 (0), now inc the next bit
mask 001 (1), initial 000 (0); initial < mask=true; initial + mask = 001--correct answer