Mengekstrak bit dengan perkalian tunggal


301

Saya melihat teknik yang menarik digunakan dalam jawaban untuk pertanyaan lain , dan ingin mengerti sedikit lebih baik.

Kami diberi integer 64-bit yang tidak ditandatangani, dan kami tertarik pada bit berikut:

1.......2.......3.......4.......5.......6.......7.......8.......

Secara khusus, kami ingin memindahkan mereka ke posisi delapan besar, seperti:

12345678........................................................

Kami tidak peduli tentang nilai bit yang ditunjukkan oleh ., dan mereka tidak harus dipertahankan.

The solusi adalah untuk menutupi keluar bit yang tidak diinginkan, dan kalikan hasilnya dengan 0x2040810204081. Ternyata ini yang berhasil.

Seberapa umum metode ini? Bisakah teknik ini digunakan untuk mengekstrak setiap subset bit? Jika tidak, bagaimana cara mengetahui apakah metode ini bekerja untuk set bit tertentu atau tidak?

Akhirnya, bagaimana cara mencari pengganda (a?) Yang benar untuk mengekstrak bit yang diberikan?


29
Jika Anda menemukan yang menarik, lihat daftar ini: graphics.stanford.edu/~seander/bithacks.html Banyak dari mereka (ab) menggunakan perkalian / pembagian integer yang lebih luas untuk mendapatkan hasil yang menarik. ("Membalik bit dalam byte dengan 4 operasi" bagian menunjukkan bagaimana menangani trik bitshift / multiplikasi ketika Anda tidak memiliki cukup ruang dan perlu untuk menutupi / mengalikan dua kali)
viraptor

@ Viraptor: Poin luar biasa. Jika Anda memahami keterbatasan metode ini, Anda benar-benar dapat menggunakan perkalian untuk menyelesaikan banyak hal sehubungan dengan manipulasi bit.
Expedito

9
Sangat menarik ada instruksi dalam AVX2 (yang sayangnya belum tersedia) yang melakukan persis operasi yang Anda jelaskan: software.intel.com/sites/products/documentation/studio/composer/…
JPvdMerwe

3
Tempat lain untuk mencari algoritma bit- twiddling yang
Barmar

1
Anda dapat terhubung dengan orang lain (e gosto bastante) di tautan
Salles

Jawaban:


235

Pertanyaan yang sangat menarik, dan trik cerdik.

Mari kita lihat contoh sederhana untuk memanipulasi byte tunggal. Menggunakan unsigned 8 bit untuk kesederhanaan. Bayangkan nomor Andaxxaxxbxx Anda dan yang Anda inginkan ab000000.

Solusinya terdiri dari dua langkah: sedikit masking, diikuti oleh perkalian. Topeng bit adalah operasi DAN sederhana yang mengubah bit tidak menarik menjadi nol. Dalam kasus di atas, topeng Anda akan menjadi00100100 dan hasilnya 00a00b00.

Sekarang bagian yang sulit: mengubahnya menjadi ab...... .

Perkalian adalah sekelompok operasi shift-and-add. Kuncinya adalah membiarkan overflow untuk "mengalihkan" bit yang tidak kita butuhkan dan meletakkan bit yang kita inginkan di tempat yang tepat.

Perkalian dengan 4 ( 00000100) akan menggeser semua yang tersisa 2 dan membuat Anda melakukannya a00b0000. Untuk mendapatkan bnaik, kita perlu mengalikan dengan 1 (untuk menjaga a di tempat yang tepat) + 4 (untuk memindahkan b ke atas). Jumlah ini adalah 5, dan dikombinasikan dengan 4 sebelumnya kita mendapatkan angka ajaib 20, atau 00010100. Yang asli 00a00b00setelah topeng; perkalian memberikan:

000000a00b000000
00000000a00b0000 +
----------------
000000a0ab0b0000
xxxxxxxxab......

Dari pendekatan ini Anda dapat memperluas ke jumlah yang lebih besar dan lebih banyak bit.

Salah satu pertanyaan yang Anda ajukan adalah "dapatkah ini dilakukan dengan sejumlah bit?" Saya pikir jawabannya adalah "tidak", kecuali jika Anda mengizinkan beberapa operasi masking, atau beberapa perkalian. Masalahnya adalah masalah "tabrakan" - misalnya, "nyasar b" dalam masalah di atas. Bayangkan kita perlu melakukan ini ke nomor seperti xaxxbxxcx. Mengikuti pendekatan sebelumnya, Anda akan berpikir kita perlu {x 2, x {1 + 4 + 16}} = x 42 (oooh - jawaban untuk semuanya!). Hasil:

00000000a00b00c00
000000a00b00c0000
0000a00b00c000000
-----------------
0000a0ababcbc0c00
xxxxxxxxabc......

Seperti yang Anda lihat, itu masih berfungsi, tetapi "hanya". Kuncinya di sini adalah bahwa ada "ruang yang cukup" antara bit yang kita inginkan sehingga kita bisa menekan semuanya. Saya tidak bisa menambahkan bit keempat d tepat setelah c, karena saya akan mendapatkan contoh di mana saya mendapatkan c + d, bit mungkin membawa ...

Jadi tanpa bukti formal, saya akan menjawab bagian yang lebih menarik dari pertanyaan Anda sebagai berikut: "Tidak, ini tidak akan bekerja untuk sejumlah bit. Untuk mengekstrak N bit, Anda perlu (N-1) spasi antara bit yang ingin Anda mengekstrak, atau memiliki langkah-langkah mask-multiply tambahan. "

Satu-satunya pengecualian yang dapat saya pikirkan untuk aturan "harus memiliki (N-1) nol di antara bit" adalah ini: jika Anda ingin mengekstrak dua bit yang berdekatan satu sama lain di aslinya, DAN Anda ingin menyimpannya di urutan yang sama, maka Anda masih bisa melakukannya. Dan untuk tujuan aturan (N-1) mereka menghitung sebagai dua bit.

Ada wawasan lain - terinspirasi oleh jawaban @Ternary di bawah ini (lihat komentar saya di sana). Untuk setiap bit yang menarik, Anda hanya perlu sebanyak nol di sebelah kanan karena Anda membutuhkan ruang untuk bit yang perlu pergi ke sana. Tetapi juga, dibutuhkan sebanyak bit ke kiri karena memiliki bit hasil ke kiri. Jadi, jika sedikit b berakhir di posisi m dari n, maka perlu memiliki m-1 nol di sebelah kirinya, dan nm nol di sebelah kanan. Terutama ketika bit tidak dalam urutan yang sama dengan nomor aslinya seperti yang akan setelah pemesanan ulang, ini merupakan peningkatan penting untuk kriteria asli. Ini berarti, misalnya, kata yang 16 bit

a...e.b...d..c..

Dapat digeser menjadi

abcde...........

meskipun hanya ada satu ruang antara e dan b, dua antara d dan c, tiga antara yang lain. Apa yang terjadi dengan N-1 ?? Dalam hal ini, a...emenjadi "satu blok" - mereka dikalikan dengan 1 untuk berakhir di tempat yang tepat, jadi "kami mendapat e gratis". Hal yang sama berlaku untuk b dan d (b membutuhkan tiga ruang ke kanan, d membutuhkan tiga yang sama ke kiri). Jadi ketika kami menghitung angka ajaib, kami menemukan ada duplikat:

a: << 0  ( x 1    )
b: << 5  ( x 32   )
c: << 11 ( x 2048 )
d: << 5  ( x 32   )  !! duplicate
e: << 0  ( x 1    )  !! duplicate

Jelas, jika Anda menginginkan angka-angka ini dalam urutan yang berbeda, Anda harus menempatkannya lebih jauh. Kita dapat merumuskan kembali (N-1)aturan: "Itu akan selalu bekerja jika ada setidaknya (N-1) ruang antara bit; atau, jika urutan bit dalam hasil akhir diketahui, maka jika bit b berakhir di posisi m dari n, harus memiliki m-1 nol di sebelah kiri, dan nm nol di sebelah kanan. "

@Ternary menunjukkan bahwa aturan ini tidak berfungsi, karena mungkin ada carry dari bit yang menambahkan "tepat di sebelah kanan area target" - yaitu, ketika bit yang kita cari adalah semuanya. Melanjutkan contoh yang saya berikan di atas dengan lima bit yang dikemas dalam kata 16 bit: jika kita mulai dengan

a...e.b...d..c..

Untuk kesederhanaan, saya akan menyebutkan posisi bit ABCDEFGHIJKLMNOP

Matematika yang akan kami lakukan adalah

ABCDEFGHIJKLMNOP

a000e0b000d00c00
0b000d00c0000000
000d00c000000000
00c0000000000000 +
----------------
abcded(b+c)0c0d00c00

Sampai sekarang, kami pikir apa pun di bawah ini abcde(posisi ABCDE) tidak masalah, tetapi pada kenyataannya, seperti yang ditunjukkan @Ternary, jika b=1, c=1, d=1kemudian (b+c)dalam posisi Gakan menyebabkan sedikit untuk dibawa ke posisi F, yang berarti bahwa (d+1)dalam posisi Fakan membawa sedikit ke dalam E- dan kami hasilnya rusak. Perhatikan bahwa ruang di sebelah kanan sedikit kepentingan paling signifikan (c dalam contoh ini) tidak masalah, karena penggandaan akan menyebabkan padding dengan nol dari sebelumnya bit paling tidak signifikan.

Jadi kita perlu memodifikasi aturan (m-1) / (nm) kita. Jika ada lebih dari satu bit yang memiliki "persis (nm) bit yang tidak digunakan ke kanan (tidak termasuk bit terakhir dalam pola -" c "pada contoh di atas), maka kita perlu memperkuat aturan - dan kita harus lakukan secara iteratif!

Kita harus melihat tidak hanya pada jumlah bit yang memenuhi kriteria (nm), tetapi juga yang ada pada (n-m + 1), dll. Mari kita sebut nomor mereka Q0 (tepat n-muntuk bit berikutnya), Q1 ( n-m + 1), hingga Q (N-1) (n-1). Maka kita berisiko membawa jika

Q0 > 1
Q0 == 1 && Q1 >= 2
Q0 == 0 && Q1 >= 4
Q0 == 1 && Q1 > 1 && Q2 >=2
... 

Jika Anda melihat ini, Anda dapat melihat bahwa jika Anda menulis ekspresi matematika sederhana

W = N * Q0 + (N - 1) * Q1 + ... + Q(N-1)

dan hasilnya adalah W > 2 * N, maka Anda perlu meningkatkan kriteria RHS sedikit demi sedikit (n-m+1). Pada titik ini, operasi aman selama W < 4; jika itu tidak berhasil, tambah satu kriteria lagi, dll.

Saya pikir mengikuti hal di atas akan membuat Anda jauh ke jawaban Anda ...


1
Bagus. Satu lagi masalah halus: tes m-1 / nm gagal beberapa kali karena membawa-bit. Coba ... b..c ... d - Anda berakhir dengan b + c di bit kelima yang jika keduanya sama-sama membuat carry bit yang clobbers d (!)
Ternary

1
Hasilnya: n-1 bit ruang melarang konfigurasi yang seharusnya berfungsi (mis. ... b..c ... d), dan m-1 / nm memungkinkan yang tidak berfungsi (a ... b..c ... d). Saya belum dapat menemukan cara sederhana untuk mengkarakterisasi mana yang akan bekerja dan mana yang tidak.
Ternary

Kamu baik! Masalah carry berarti kita membutuhkan sedikit lebih banyak ruang di sebelah kanan setiap bit sebagai "perlindungan". Pada pandangan pertama, jika setidaknya ada dua bit yang memiliki tepat minimum nm ke kanan, Anda perlu menambah ruang dengan 1. Secara umum, jika ada P bit seperti itu, Anda perlu log2 (P) bit tambahan ke hak apa pun yang memiliki minimum (mn). Tampaknya benar bagi Anda?
Floris

Nah, komentar terakhir itu terlalu sederhana. Saya pikir jawaban saya yang terakhir diedit menunjukkan bahwa log2 (P) bukan pendekatan yang tepat. @ Jawaban Ternary sendiri (di bawah) menunjukkan dengan elegan bagaimana Anda dapat mengatakan untuk kombinasi bit tertentu jika Anda tidak memiliki solusi yang dijamin - Saya percaya pekerjaan di atas menjelaskan lebih banyak lagi.
Floris

1
Ini mungkin kebetulan, tetapi jawaban ini diterima ketika jumlah upvote mencapai 127. Jika Anda telah membaca sejauh ini, Anda akan tersenyum dengan saya ...
Floris

154

Pertanyaan yang sangat menarik. Saya menyinggung dua sen saya, yaitu, jika Anda dapat mengatur untuk menyatakan masalah seperti ini dalam hal logika tingkat pertama atas teori bitvector, maka pembalik teorema adalah teman Anda, dan berpotensi memberi Anda sangat cepat jawaban atas pertanyaan Anda. Mari kita nyatakan kembali masalah yang ditanyakan sebagai teorema:

"Ada beberapa konstanta 64-bit 'mask' dan 'multiplicand' sedemikian rupa sehingga, untuk semua bitvektor 64-bit x, dalam ekspresi y = (x & mask) * multiplicand, kita memiliki y.63 == x.63 , y.62 == x.55, y.61 == x.47, dll. "

Jika kalimat ini sebenarnya adalah teorema, maka memang benar bahwa beberapa nilai konstanta 'topeng' dan 'multiplicand' memenuhi sifat ini. Jadi mari kita frase ini dalam hal sesuatu yang dapat dipahami oleh sebuah teorema teorema, yaitu input SMT-LIB 2:

(set-logic BV)

(declare-const mask         (_ BitVec 64))
(declare-const multiplicand (_ BitVec 64))

(assert
  (forall ((x (_ BitVec 64)))
    (let ((y (bvmul (bvand mask x) multiplicand)))
      (and
        (= ((_ extract 63 63) x) ((_ extract 63 63) y))
        (= ((_ extract 55 55) x) ((_ extract 62 62) y))
        (= ((_ extract 47 47) x) ((_ extract 61 61) y))
        (= ((_ extract 39 39) x) ((_ extract 60 60) y))
        (= ((_ extract 31 31) x) ((_ extract 59 59) y))
        (= ((_ extract 23 23) x) ((_ extract 58 58) y))
        (= ((_ extract 15 15) x) ((_ extract 57 57) y))
        (= ((_ extract  7  7) x) ((_ extract 56 56) y))
      )
    )
  )
)

(check-sat)
(get-model)

Dan sekarang mari kita tanyakan pada teorema Z3 apakah ini adalah teorema:

z3.exe /m /smt2 ExtractBitsThroughAndWithMultiplication.smt2

Hasilnya adalah:

sat
(model
  (define-fun mask () (_ BitVec 64)
    #x8080808080808080)
  (define-fun multiplicand () (_ BitVec 64)
    #x0002040810204081)
)

Bingo! Ini mereproduksi hasil yang diberikan dalam posting asli dalam 0,06 detik.

Melihat ini dari perspektif yang lebih umum, kita dapat melihat ini sebagai contoh dari masalah sintesis program tingkat pertama, yang merupakan bidang penelitian yang baru muncul tentang beberapa makalah yang telah diterbitkan. Pencarian "program synthesis" filetype:pdfharus membantu Anda memulai.


2
Saya terkesan! Saya tidak tahu bahwa "logika tingkat pertama atas teori bitvector" bahkan merupakan subjek nyata yang dipelajari orang - apalagi itu bisa memberikan hasil yang menarik. Terima kasih banyak untuk membagikan ini.
Floris

@AndrewBacker: Bisakah seseorang menerangi saya sampai titik apa dalam hal yang disebut "SO-as-a-job" ini? Maksudku, itu tidak membayar apa pun. Anda tidak dapat hidup hanya dengan perwakilan pribadi. Mungkin itu bisa memberi Anda beberapa poin dalam wawancara. Mungkin. Jika tempat kerja cukup baik untuk mengenali nilai perwakilan SO, dan itu tidak diberikan ...
Reinstate Monica

3
Tentu. SO juga merupakan permainan (apa pun yang memiliki poin) untuk banyak orang. Hanya sifat manusia, seperti berburu di / r / baru sehingga Anda dapat memposting komentar pertama dan mendapatkan karma. Tidak ada yang buruk tentang itu, selama jawabannya masih bagus. Saya lebih bahagia bisa meningkatkan waktu dan upaya seseorang ketika mereka mungkin benar-benar memperhatikan bahwa seseorang melakukannya. Dorongan adalah hal yang baik :) Dan ... itu komentar yang sangat lama, dan masih benar. Saya tidak mengerti bagaimana itu tidak jelas.
Andrew Backer

88

Setiap 1-bit dalam pengali digunakan untuk menyalin salah satu bit ke posisi yang benar:

  • 1sudah dalam posisi yang benar, jadi kalikan dengan 0x0000000000000001.
  • 2 harus digeser posisi 7 bit ke kiri, jadi kita kalikan dengan 0x0000000000000080 (bit 7 diatur).
  • 3harus digeser posisi 14 bit ke kiri, jadi kita kalikan dengan 0x0000000000000400(bit 14 diatur).
  • dan seterusnya sampai
  • 8harus digeser posisi 49 bit ke kiri, jadi kita kalikan dengan 0x0002000000000000(bit 49 diatur).

Pengganda adalah jumlah dari pengganda untuk bit individual.

Ini hanya berfungsi karena bit yang dikumpulkan tidak terlalu berdekatan, sehingga penggandaan bit yang tidak termasuk dalam skema kami berada di luar 64 bit atau di bagian tidak peduli yang lebih rendah.

Perhatikan bahwa bit lain dalam nomor aslinya harus 0. Ini dapat dicapai dengan menutupi mereka dengan operasi DAN.


2
Penjelasan hebat! Jawaban singkat Anda memungkinkan untuk dengan cepat menemukan nilai "angka ajaib".
Expedito

4
Ini benar-benar jawaban terbaik, tetapi itu tidak akan sangat membantu tanpa membaca (bagian pertama) dari jawaban @ floris terlebih dahulu.
Andrew Backer

29

(Aku belum pernah melihatnya sebelumnya. Trik ini hebat!)

Saya akan memperluas sedikit pada pernyataan Floris bahwa ketika mengekstraksi nbit Anda memerlukan n-1ruang antara bit yang tidak berurutan:

Pikiran awal saya (kita akan lihat sebentar lagi bagaimana ini tidak cukup berhasil) adalah bahwa Anda bisa melakukan lebih baik: Jika Anda ingin mengekstrak nbit, Anda akan memiliki tabrakan ketika mengekstraksi / menggeser bit ijika Anda memiliki orang lain (non -berjalan dengan bit i) pada i-1bit sebelumnya ataun-i bit-bit berikutnya.

Saya akan memberikan beberapa contoh untuk menggambarkan:

...a..b...c...Bekerja (tidak ada dalam 2 bit setelah a, bit sebelum dan sedikit setelah b, dan tidak ada yang ada di 2 bit sebelumnya c):

  a00b000c
+ 0b000c00
+ 00c00000
= abc.....

...a.b....c...Gagal karena bada dalam 2 bit setelah a(dan akan ditarik ke tempat orang lain ketika kita bergeser a):

  a0b0000c
+ 0b0000c0
+ 00c00000
= abX.....

...a...b.c...Gagal karena bada dalam 2 bit sebelumnya c(dan terdorong ke tempat orang lain ketika kita bergeser c):

  a000b0c0
+ 0b0c0000
+ b0c00000
= Xbc.....

...a...bc...d... Bekerja karena bit berturut-turut bergeser bersama:

  a000bc000d
+ 0bc000d000
+ 000d000000
= abcd000000

Tapi kami punya masalah. Jika kita menggunakan n-ialih-alih n-1kita dapat memiliki skenario berikut: bagaimana jika kita memiliki tabrakan di luar bagian yang kita pedulikan, sesuatu yang kita akan sembunyikan di bagian akhir, tetapi bit pengangkutnya yang akhirnya mengganggu jangkauan penting tanpa-penutup ? (dan perhatikan: n-1persyaratan memastikan ini tidak terjadi dengan memastikan i-1bit setelah rentang un-masked kami jelas ketika kami menggeser ibit th)

...a...b..c...d...Potensi kegagalan pada carry-bit, cada n-1setelahnya b, tetapi memenuhi n-ikriteria:

  a000b00c000d
+ 0b00c000d000
+ 00c000d00000
+ 000d00000000
= abcdX.......

Jadi mengapa kita tidak kembali saja ke n-1persyaratan " sedikit ruang" itu? Karena kita dapat melakukan yang lebih baik :

...a....b..c...d.. Gagal pada n-1tes " bit of space", tetapi bekerja untuk trik penggalian bit kami:

+ a0000b00c000d00
+ 0b00c000d000000
+ 00c000d00000000
+ 000d00000000000
= abcd...0X......

Saya tidak dapat menemukan cara yang baik untuk mengkarakterisasi bidang-bidang ini yang tidak memiliki n-1ruang di antara bit-bit penting, tetapi masih akan bekerja untuk operasi kami. Namun, karena kita tahu sebelumnya bit mana yang kami minati, kami dapat memeriksa filter kami untuk memastikan kami tidak mengalami tabrakan carry-bit:

Bandingkan (-1 AND mask) * shiftdengan hasil semua yang diharapkan,-1 << (64-n) (untuk 64-bit yang tidak ditandatangani)

Pergeseran ajaib / gandakan untuk mengekstrak bit kita berfungsi jika dan hanya jika keduanya sama.


Saya suka - Anda benar bahwa untuk setiap bit, Anda hanya perlu sebanyak nol di sebelah kanan karena Anda memerlukan ruang untuk bit yang perlu pergi ke sana. Tetapi juga , dibutuhkan sebanyak bit ke kiri karena memiliki bit hasil ke kiri. Jadi, jika sedikit bberakhir di posisi mdari n, maka perlu memiliki m-1nol ke kiri, dan n-m-1nol ke kanan. Terutama ketika bit tidak dalam urutan yang sama dengan nomor aslinya seperti yang akan setelah pemesanan ulang, ini merupakan peningkatan penting untuk kriteria asli. Ini menyenangkan.
Floris

13

Selain jawaban yang sudah sangat bagus untuk pertanyaan yang sangat menarik ini, mungkin berguna untuk mengetahui bahwa trik penggandaan bitwise ini telah dikenal di komunitas catur komputer sejak 2007, di mana ia berjalan dengan nama Magic BitBoards .

Banyak mesin catur komputer menggunakan beberapa bilangan bulat 64-bit (disebut bitboard) untuk mewakili berbagai set piece (1 bit per persegi yang diduduki). Misalkan potongan geser (benteng, uskup, ratu) pada kotak asal tertentu dapat bergerak ke paling banyak Kkotak jika tidak ada potongan penghalang yang hadir. Menggunakan bitwise-dan Kbit - bit yang tersebar dengan bitboard dari kotak yang ditempati memberikan Kkata-bit khusus yang tertanam dalam integer 64-bit.

Perkalian ajaib dapat digunakan untuk memetakan Kbit - bit yang tersebar ini ke bit yang lebih rendah Kdari integer 64-bit. KBit-bit yang lebih rendah ini kemudian dapat digunakan untuk mengindeks tabel dari bitboard yang telah dikomputasi sebelumnya yang mewakili kotak yang diizinkan yang dapat dipindahkan oleh potongan pada kuadrat asalnya (merawat blokir potongan dll.)

Mesin catur biasa yang menggunakan pendekatan ini memiliki 2 tabel (satu untuk benteng, satu untuk uskup, ratu menggunakan kombinasi keduanya) dari 64 entri (satu per kotak asal) yang berisi hasil yang telah dihitung sebelumnya. Baik sumber tertutup berperingkat tertinggi ( Houdini ) dan mesin catur open source ( Stockfish ) saat ini menggunakan pendekatan ini untuk kinerjanya yang sangat tinggi.

Menemukan pengganda ajaib ini dilakukan baik menggunakan pencarian lengkap (dioptimalkan dengan cutoff awal) atau dengan uji coba dan kesalahan (misalnya mencoba banyak bilangan bulat 64-bit acak). Tidak ada pola bit yang digunakan selama generasi bergerak yang tidak ada konstanta sihir yang dapat ditemukan. Namun, efek carry bitwise biasanya diperlukan ketika bit yang akan dipetakan memiliki (hampir) indeks yang berdekatan.

AFAIK, pendekatan SAT-solver yang sangat umum oleh @Syzygy belum pernah digunakan dalam catur komputer, dan tampaknya juga tidak ada teori formal tentang keberadaan dan keunikan konstanta sihir semacam itu.


Saya akan berpikir bahwa siapa pun yang memiliki latar belakang CS formal penuh akan melompat pada pendekatan SAT langsung setelah melihat masalah ini. Mungkin orang-orang CS menemukan catur tidak menarik? :(
Reinstate Monica

@KubaOber Sebagian besar sebaliknya: catur komputer didominasi oleh bit-twiddlers yang memprogram dalam C atau assembly, dan membenci segala jenis abstraksi (C ++, templates, OO). Saya pikir itu menakut-nakuti orang-orang CS nyata :-)
TemplateRex
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.