C#最初の1(右から左)の2進数


10

C#を使用して、数値のバイナリ表現で最初の1(右から左)のインデックスを見つけようとしています。たとえば、バイナリの100は次のとおりです。

0b1100100

最初の1は右から3番目の位置にあるため、3になります。

234は2を生成し、0は0を生成します。

これが私の現在の解決策です:

k < 1 ? 0 :(int)Math.Log(k & -k, 2) + 1;

これを短くする方法はありますか?


1
明らかなヒントは、無関係な空白を削除することです。簡単に削除できるスペースが10個あります。
James

Convert.ToString(k,2).IndexOf("1")あなたが望むもの、または似たような間違ったサイトです。
マジックタコの壷

14
@ close-voters-なぜclose-votesですか?これはトピックに関するヒントの質問だと思います。または、この点で見逃したルールの変更はありますか?
デジタルトラウマ

回答:


3

C#のみがマシン固有の組み込み関数をサポートしている場合…x86アセンブリ言語でこれを実行できる単一の命令があり、他のほとんどのプロセッサアーキテクチャでも同様です。そうすると、最短のコードだけでなく、最速のコードになる可能性が非常に高くなります。

実際、このコードを短くすることは、このコードを高速にすることに比べて非常に退屈な問題です。あらゆる種類の本当にきちんとした、効率的な、ビットをいじるソリューションがあり、ルックアップテーブルの使用を検討することもできます。

ただし、ゴルフにとってそれは重要ではありません。あなたの現在の解決策はあなたができる最善のように思えます。もちろん、余分な空白を削除することができます:

k<1?0:(int)Math.Log(k&-k,2)+1

私は個人的にそれを次のように書きます:

k>0?(int)Math.Log(k&-k,2)+1:0

条件付きテストの方向をそのようにしたり、ゼロと比較したりすることは少し明確だと思うので、私はそれが6つの方法であり、他の半ダースだと思います。

C#は、CやC ++のようなからintへの暗黙的な変換をサポートしていないboolため、条件テストをこれ以上短くすることはできません。

また、C#では暗黙的にこれが発生することを許可していないため、double(my から返されたMath.Log)からへの明示的なキャストにint悩まされています。それはあなたが持っていることを指摘してしまうため、もちろん、それは通常、良いことだ大きな推進:ここでのパフォーマンスの問題をintするdouble、のログを計算doubleして、変換doubleに結果バックすることintになり、大規模な、それは通常、何かですので、遅いですあなたが避けたいと思うこと。しかし、これらはコードゴルフをするときに我慢しなければならない種類の倒錯です。


私は最初に思いついた

k > 0
      ? ((k & -k) >> 1) + 1
      : 0

(もちろん、わかりやすくするために無記号)、これは対数を取ることを回避するため、コードのサイズと速度が向上します。残念ながら、これは常に正しい答えを得るとは限りません。私はそれが柔軟性のない要件であると思います。:-)具体的には、入力値(k)が8の係数である場合に失敗します。これはMath.Log修正可能ですが、バージョンよりもコードを長くしないと修正できません。


コードゴルフのMath場合、完全に修飾する必要があるため、実際にはバイトをカウントしていませんが、他のバージョンの方が適していることに注意してください。
TheLethalCoder 2017

間違った出力を生成するものですか?@the
コーディグレイ

まああなたはそれに修正があると言いましたが、それはそれをより長くするでしょう。修正がOPバージョンに含まれている場合よりも短い場合は、System.短くて正しいはずです。
TheLethalCoder 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.