C # Pertama 1 (kanan ke kiri) dalam angka biner

10

Saya mencoba menggunakan C # untuk menemukan indeks 1 pertama (kanan ke kiri) dalam representasi biner angka. Misalnya, karena 100 dalam biner adalah:

0b1100100

1 pertama ada di posisi ketiga dari kanan, jadi harus menghasilkan 3.

234 harus menghasilkan 2, 0 harus menghasilkan 0, dll.

Inilah solusi saya saat ini:

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

Adakah cara saya bisa membuat ini lebih pendek?

Eric Cepress
sumber
1
Ujung yang jelas adalah untuk menghapus spasi kosong Anda. Saya melihat 10 spasi yang bisa Anda hapus dengan mudah.
James
Convert.ToString(k,2).IndexOf("1")adalah apa yang Anda inginkan, atau sesuatu yang serupa, situs yang salah.
Magic Octopus Urn
14
@ close-voters - Mengapa suara dekat? Saya pikir ini adalah pertanyaan kiat tentang topik . Atau apakah ada perubahan peraturan yang saya lewatkan dalam hal ini?
Digital Trauma

Jawaban:

3

Jika hanya C # mendukung intrinsik khusus-mesin… Ada satu instruksi yang dapat melakukan ini dalam bahasa assembly x86, dan pada sebagian besar arsitektur prosesor lainnya juga. Maka Anda tidak hanya memiliki kode terpendek, tetapi sangat mungkin tercepat.

Sebenarnya, membuat kode ini lebih pendek adalah masalah yang sangat membosankan dibandingkan dengan membuat kode ini cepat . Ada segala macam solusi yang benar-benar rapi, efisien, sedikit membingungkan, dan Anda juga bisa mempertimbangkan menggunakan tabel pencarian.

Tidak ada yang penting untuk bermain golf. Menurut saya solusi Anda saat ini adalah yang terbaik yang dapat Anda lakukan. Tentu saja, Anda dapat menghapus spasi putih berlebihan:

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

Saya pribadi akan menuliskannya sebagai:

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

karena saya pikir itu sedikit lebih jelas untuk memiliki arah tes bersyarat seperti itu, serta membandingkannya dengan nol, tapi saya kira itu enam satu arah, setengah lusin lainnya.

C # tidak mendukung konversi implisit dari intke boolseperti C dan C ++ lakukan, sehingga Anda tidak bisa benar-benar mempersingkat uji kondisional lebih jauh.

Anda juga terjebak dengan pemeran eksplisit dari double(seperti mengembalikan saya Math.Log) ke int, karena C # tidak akan membiarkan ini terjadi secara implisit. Tentu saja, itu biasanya hal yang baik karena itu akan menunjukkan bahwa Anda memiliki masalah kinerja besar di sini: mempromosikan intke double, menghitung log dari double, dan kemudian mengonversi doublehasilnya kembali ke intakan menjadi sangat lambat, jadi biasanya sesuatu yang ingin Anda hindari. Tapi ini adalah jenis penyimpangan yang harus Anda lakukan ketika bermain golf kode.


Saya awalnya datang dengan

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

(Tidak diserang untuk kejelasan, tentu saja), yang menghindari pengambilan logaritma dan karena itu merupakan peningkatan dalam ukuran dan kecepatan kode. Sayangnya, ini tidak selalu mendapatkan jawaban yang benar, dan saya menganggap itu merupakan persyaratan yang tidak fleksibel. :-) Secara khusus, gagal jika nilai input ( k) adalah faktor 8. Ini dapat diperbaiki, tetapi bukan tanpa membuat kode lebih lama dari Math.Logversi.

Cody Grey
sumber
Perhatikan bahwa untuk golf kode Mathharus sepenuhnya memenuhi syarat sehingga versi Anda yang lain harus lebih baik walaupun saya belum benar-benar menghitung byte.
TheLethalCoder
Maksud Anda yang menghasilkan output yang salah? @the
Cody Grey
Yah Anda mengatakan ada perbaikan untuk itu tetapi itu akan membuatnya lebih lama. Jika perbaikan lebih pendek daripada ketika versi OPs termasuk System.maka itu harus lebih pendek dan benar.
TheLethalCoder