Trích xuất bit với một phép nhân


301

Tôi thấy một kỹ thuật thú vị được sử dụng trong một câu trả lời cho một câu hỏi khác , và muốn hiểu nó tốt hơn một chút.

Chúng tôi đã cung cấp một số nguyên 64 bit không dấu và chúng tôi quan tâm đến các bit sau:

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

Cụ thể, chúng tôi muốn chuyển chúng lên tám vị trí hàng đầu, như vậy:

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

Chúng tôi không quan tâm đến giá trị của các bit được chỉ định bởi .và chúng không phải được bảo tồn.

Các giải pháp là để mặt nạ ra các bit không mong muốn, và nhân kết quả bằng 0x2040810204081. Điều này, như hóa ra, thực hiện các mẹo.

Làm thế nào chung là phương pháp này? Kỹ thuật này có thể được sử dụng để trích xuất bất kỳ tập hợp con bit nào không? Nếu không, làm thế nào để tìm ra liệu phương thức này có hoạt động đối với một tập hợp bit cụ thể không?

Cuối cùng, làm thế nào người ta sẽ đi tìm số nhân chính xác (a?) Để trích xuất các bit đã cho?


29
Nếu bạn thấy một điều thú vị, hãy xem danh sách này: Graphics.stanford.edu/~seander/bithacks.html Rất nhiều trong số họ (ab) sử dụng phép nhân / chia số nguyên rộng hơn để đạt được kết quả thú vị. (Phần "Đảo ngược các bit trong một byte với 4 thao tác" cho thấy cách xử lý thủ thuật bẻ / nhân khi bạn không có đủ dung lượng và cần che / nhân hai lần)
viraptor 27/1/13

@viraptor: Điểm tuyệt vời. Nếu bạn hiểu những hạn chế của phương pháp này, bạn thực sự có thể sử dụng phép nhân để hoàn thành rất nhiều việc liên quan đến thao tác bit.
Expedito

9
Thật thú vị, có một hướng dẫn trong AVX2 (đáng buồn là chưa có sẵn) thực hiện chính xác thao tác mà bạn mô tả: software.intel.com/sites/products/documentation/studio/composer/iêu
JPvdMerwe 27/1/13

3
Một nơi khác để tìm kiếm các thuật toán xoay vòng
Barmar

1
Um livro que conheço sobre o assunto (e gosto bastante) é o "Hacker của Delight" liên kết
Salles

Câu trả lời:


235

Câu hỏi rất thú vị, và mẹo thông minh.

Hãy xem xét một ví dụ đơn giản về việc thao tác một byte đơn. Sử dụng 8 bit không dấu để đơn giản. Hãy tưởng tượng số của bạn là xxaxxbxxvà bạn muốn ab000000.

Giải pháp bao gồm hai bước: một mặt nạ bit, tiếp theo là nhân. Mặt nạ bit là một hoạt động đơn giản VÀ biến các bit không thú vị thành số không. Trong trường hợp trên, mặt nạ của bạn sẽ được 00100100và kết quả 00a00b00.

Bây giờ là phần khó: biến điều đó thành ab.......

Phép nhân là một loạt các hoạt động thay đổi và thêm. Điều quan trọng là cho phép tràn để "dịch chuyển" các bit mà chúng ta không cần và đặt các bit chúng ta muốn vào đúng vị trí.

Phép nhân với 4 ( 00000100) sẽ thay đổi mọi thứ còn lại bằng 2 và đưa bạn đến a00b0000. Để bdi chuyển lên, chúng ta cần nhân với 1 (để giữ a ở đúng vị trí) + 4 (để di chuyển b lên). Tổng này là 5, và kết hợp với 4 trước đó, chúng ta có được số ma thuật là 20, hoặc 00010100. Bản gốc là 00a00b00sau khi đắp mặt nạ; phép nhân cho:

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

Từ phương pháp này, bạn có thể mở rộng đến số lượng lớn hơn và nhiều bit hơn.

Một trong những câu hỏi bạn đặt ra là "điều này có thể được thực hiện với bất kỳ số bit nào không?" Tôi nghĩ câu trả lời là "không", trừ khi bạn cho phép một vài thao tác che giấu, hoặc một vài phép nhân. Vấn đề là vấn đề "va chạm" - ví dụ: "b đi lạc" trong vấn đề trên. Hãy tưởng tượng chúng ta cần phải làm điều này đến một số như thế xaxxbxxcx. Theo cách tiếp cận trước đó, bạn sẽ nghĩ rằng chúng tôi cần {x 2, x {1 + 4 + 16}} = x 42 (oooh - câu trả lời cho mọi thứ!). Kết quả:

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

Như bạn có thể thấy, nó vẫn hoạt động, nhưng "chỉ". Chìa khóa ở đây là có "đủ không gian" giữa các bit mà chúng ta muốn mà chúng ta có thể ép mọi thứ lên. Tôi không thể thêm bit thứ tư ngay sau c, vì tôi sẽ nhận được các trường hợp tôi nhận được c + d, bit có thể mang, ...

Vì vậy, nếu không có bằng chứng chính thức, tôi sẽ trả lời các phần thú vị hơn trong câu hỏi của bạn như sau: "Không, điều này sẽ không hoạt động đối với bất kỳ số bit nào. Để trích xuất N bit, bạn cần khoảng trống (N-1) giữa các bit bạn muốn giải nén hoặc có các bước nhân mặt nạ bổ sung. "

Ngoại lệ duy nhất tôi có thể nghĩ đến cho quy tắc "phải có (N-1) giữa các bit" là: nếu bạn muốn trích xuất hai bit liền kề nhau trong bản gốc, VÀ bạn muốn giữ chúng trong cùng một thứ tự, sau đó bạn vẫn có thể làm điều đó. Và với mục đích của quy tắc (N-1), chúng được tính là hai bit.

Có một cái nhìn sâu sắc khác - lấy cảm hứng từ câu trả lời của @Ternary bên dưới (xem bình luận của tôi ở đó). Đối với mỗi bit thú vị, bạn chỉ cần có nhiều số không ở bên phải của nó vì bạn cần không gian cho các bit cần đến đó. Nhưng ngoài ra, nó cần nhiều bit ở bên trái vì nó có các bit kết quả ở bên trái. Vì vậy, nếu một bit b kết thúc ở vị trí m của n, thì nó cần phải có các số 0 m-1 ở bên trái của nó, và các số 0 ở bên phải của nó. Đặc biệt là khi các bit không theo cùng thứ tự trong số ban đầu như sau khi sắp xếp lại, đây là một cải tiến quan trọng đối với các tiêu chí ban đầu. Điều này có nghĩa là, ví dụ, một từ 16 bit

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

Có thể chuyển sang

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

mặc dù chỉ có một khoảng cách giữa e và b, hai giữa d và c, ba giữa hai cái khác. Chuyện gì đã xảy ra với N-1 ?? Trong trường hợp này, a...etrở thành "một khối" - chúng được nhân với 1 để kết thúc ở đúng nơi, và vì vậy "chúng tôi đã nhận e miễn phí". Điều này cũng đúng với b và d (b cần ba khoảng trắng ở bên phải, d cần ba khoảng trắng ở bên trái). Vì vậy, khi chúng tôi tính toán số ma thuật, chúng tôi thấy có những bản sao:

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

Rõ ràng, nếu bạn muốn những con số này theo một thứ tự khác, bạn sẽ phải sắp xếp chúng thêm nữa. Chúng ta có thể định dạng lại (N-1)quy tắc: "Nó sẽ luôn hoạt động nếu có ít nhất (N-1) khoảng cách giữa các bit; hoặc, nếu biết thứ tự các bit trong kết quả cuối cùng, thì nếu một bit b kết thúc ở vị trí m của n, nó cần phải có các số 0 m ở bên trái và các số 0 ở bên phải. "

@Ternary chỉ ra rằng quy tắc này không thực sự hiệu quả, vì có thể thực hiện từ các bit thêm "ngay bên phải của khu vực mục tiêu" - cụ thể là khi các bit chúng ta tìm kiếm đều là các bit. Tiếp tục ví dụ tôi đã đưa ra ở trên với năm bit được đóng gói chặt chẽ trong một từ 16 bit: nếu chúng ta bắt đầu bằng

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

Để đơn giản, tôi sẽ đặt tên cho các vị trí bit ABCDEFGHIJKLMNOP

Toán học chúng ta sẽ làm là

ABCDEFGHIJKLMNOP

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

Cho đến bây giờ, chúng tôi nghĩ rằng bất cứ điều gì bên dưới abcde(vị trí ABCDE) sẽ không quan trọng, nhưng thực tế, như @Ternary đã chỉ ra, nếu b=1, c=1, d=1sau đó (b+c)tại vị trí Gsẽ gây ra một chút để mang đến vị trí F, điều đó có nghĩa là (d+1)ở vị trí Fsẽ mang một chút vào E- và của chúng tôi kết quả là hư hỏng Lưu ý rằng không gian bên phải của bit quan tâm ít nhất ( ctrong ví dụ này) không thành vấn đề, vì phép nhân sẽ gây ra đệm với các số không từ beyone bit ít quan trọng nhất.

Vì vậy, chúng ta cần sửa đổi quy tắc (m-1) / (nm) của mình. Nếu có nhiều hơn một bit có "chính xác (nm) bit không được sử dụng ở bên phải (không tính bit cuối cùng trong mẫu -" c "trong ví dụ trên), thì chúng ta cần tăng cường quy tắc - và chúng ta phải làm như vậy lặp đi lặp lại!

Chúng ta không chỉ nhìn vào số bit đáp ứng tiêu chí (nm), mà cả số bit đang ở (n-m + 1), v.v. Hãy gọi số của chúng là Q0 (chính xác n-mđến bit tiếp theo), Q1 ( n-m + 1), tối đa Q (N-1) (n-1). Sau đó, chúng tôi có nguy cơ thực hiện nếu

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

Nếu bạn nhìn vào điều này, bạn có thể thấy rằng nếu bạn viết một biểu thức toán học đơn giản

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

và kết quả là W > 2 * N, sau đó bạn cần tăng tiêu chí RHS thêm một chút để (n-m+1). Tại thời điểm này, hoạt động là an toàn miễn là W < 4; nếu điều đó không hiệu quả, hãy tăng thêm tiêu chí, v.v.

Tôi nghĩ rằng làm theo những điều trên sẽ giúp bạn có một câu trả lời dài ...


1
Tuyệt quá. Một vấn đề tinh tế hơn: thử nghiệm m-1 / nm thất bại một số thời gian do các bit mang. Hãy thử một ... b..c ... d - bạn kết thúc với b + c ở bit thứ năm, nếu cả hai đều tạo ra một bit mang theo mà
bịt kín

1
upshot: n-1 bit của không gian cấm các cấu hình nên hoạt động (iea ... b..c ... d) và m-1 / nm cho phép các cấu hình không hoạt động (a ... b..c ... d). Tôi đã không thể đưa ra một cách đơn giản để mô tả cái nào sẽ hoạt động và cái nào sẽ không.
Ternary

Bạn tốt quá Vấn đề mang có nghĩa là chúng ta cần thêm một chút không gian ở bên phải của mỗi bit là "bảo vệ". Thoạt nhìn, nếu có ít nhất hai bit có chính xác bước sóng tối thiểu ở bên phải, bạn cần tăng khoảng trống thêm 1. Nói chung, nếu có P bit như vậy, bạn cần các bit bổ sung log2 (P) cho quyền của bất kỳ cái nào có mức tối thiểu (mn). Có vẻ đúng với bạn?
Floris

Vâng, nhận xét cuối cùng là quá đơn giản. Tôi nghĩ rằng câu trả lời được chỉnh sửa gần đây nhất của tôi cho thấy rằng log2 (P) không phải là phương pháp phù hợp. Câu trả lời của chính @ Ternary (bên dưới) cho thấy một cách thanh lịch cách bạn có thể nói cho một sự kết hợp bit cụ thể nếu bạn không có giải pháp bảo đảm - Tôi tin rằng công việc trên sẽ giải thích thêm về điều đó.
Floris

1
Đây có thể là một sự trùng hợp ngẫu nhiên, nhưng câu trả lời này đã được chấp nhận khi số lượng upvote lên tới 127. Nếu bạn đã đọc đến đây, bạn sẽ mỉm cười với tôi ...
Floris

154

Câu hỏi rất thú vị thực sự. Tôi đang chú ý đến hai xu của mình, đó là, nếu bạn có thể xử lý các vấn đề như thế này theo logic thứ nhất so với lý thuyết bitvector, thì các định lý định lý là bạn của bạn và có khả năng cung cấp cho bạn rất nhanh Trả lời cho những câu hỏi của bạn. Hãy nêu lại vấn đề đang được hỏi như một định lý:

"Tồn tại một số hằng 64 bit 'mặt nạ' và 'bội số' sao cho tất cả các bit 64 bit x, trong biểu thức y = (x & mask) * nhân, chúng ta có y.63 == x.63 , y.62 == x.55, y.61 == x.47, v.v. "

Nếu câu này thực tế là một định lý, thì đúng là một số giá trị của hằng số 'mặt nạ' và 'bội số' thỏa mãn tính chất này. Vì vậy, hãy diễn đạt điều này theo nghĩa của một điều mà một người ủng hộ định lý có thể hiểu, cụ thể là đầu vào 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)

Và bây giờ, hãy hỏi định lý Z3 xem đây có phải là một định lý không:

z3.exe /m /smt2 ExtractBitsThroughAndWithMultiplication.smt2

Kết quả là:

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

Chơi lô tô! Nó tái tạo kết quả được đưa ra trong bài viết gốc trong 0,06 giây.

Nhìn từ góc độ tổng quát hơn, chúng ta có thể xem đây là một ví dụ của một vấn đề tổng hợp chương trình đặt hàng đầu tiên, đây là một lĩnh vực nghiên cứu mới về việc ít bài báo nào được xuất bản. Một tìm kiếm "program synthesis" filetype:pdfsẽ giúp bạn bắt đầu.


2
Tôi rất ấn tượng! Tôi không biết rằng "logic thứ nhất so với lý thuyết bitvector" thậm chí là một chủ đề thực sự mà mọi người nghiên cứu - chứ đừng nói rằng nó có thể mang lại kết quả thú vị như vậy. Cảm ơn rất nhiều vì đã chia sẻ điều này.
Floris

@AndrewBacker: Ai đó có thể chiếu sáng cho tôi xem điểm nào trong cái gọi là "SO-as-a-job" này không? Ý tôi là, nó không trả bất cứ thứ gì. Bạn không thể sống một mình trên SO rep. Có lẽ nó có thể cung cấp cho bạn một số điểm trong các cuộc phỏng vấn. Có lẽ. Nếu nơi làm việc đủ tốt để nhận ra giá trị của đại diện SO, và đó không phải là một ...
Tái lập lại

3
Chắc chắn rồi. SO cũng là một trò chơi (bất cứ điều gì có điểm) cho rất nhiều người. Chỉ cần bản chất con người, thích săn bắn trong / r / mới để bạn có thể đăng bình luận đầu tiên và nhận nghiệp. Không có gì xấu về nó, miễn là câu trả lời vẫn còn tốt. Tôi chỉ vui hơn khi có thể nâng cao thời gian và nỗ lực của ai đó khi họ có khả năng thực sự nhận thấy rằng ai đó đã làm. Sự khuyến khích là thứ tốt :) Và ... đó là một nhận xét thực sự cũ, và vẫn đúng. Tôi không thấy nó không rõ ràng.
Andrew Backer

88

Mỗi 1 bit trong hệ số nhân được sử dụng để sao chép một trong các bit vào đúng vị trí của nó:

  • 1đã ở đúng vị trí, nên nhân với 0x0000000000000001.
  • 2phải được dịch chuyển vị trí 7 bit sang trái, vì vậy chúng tôi nhân với 0x0000000000000080(bit 7 được đặt).
  • 3phải được dịch chuyển vị trí 14 bit sang trái, vì vậy chúng tôi nhân với 0x0000000000000400(bit 14 được đặt).
  • và cứ thế cho đến khi
  • 8phải được dịch chuyển vị trí 49 bit sang trái, vì vậy chúng tôi nhân với 0x0002000000000000(bit 49 được đặt).

Số nhân là tổng số nhân cho các bit riêng lẻ.

Điều này chỉ hoạt động vì các bit được thu thập không quá gần nhau, do đó, việc nhân các bit không thuộc về nhau trong sơ đồ của chúng tôi vượt quá 64 bit hoặc ở phần không quan tâm thấp hơn.

Lưu ý rằng các bit khác trong số gốc phải là 0. Điều này có thể đạt được bằng cách che dấu chúng bằng thao tác AND.


2
Giải thích tuyệt vời! Câu trả lời ngắn gọn của bạn giúp bạn có thể nhanh chóng tìm thấy giá trị của "số ma thuật".
Expedito

4
Đây thực sự là câu trả lời tốt nhất, nhưng sẽ không hữu ích nếu không đọc (nửa đầu) câu trả lời của @ floris trước.
Andrew Backer

29

(Tôi chưa bao giờ nhìn thấy nó trước đây. Thủ thuật này rất hay!)

Tôi sẽ mở rộng một chút về khẳng định của Floris rằng khi trích xuất nbit bạn cần n-1khoảng trống giữa bất kỳ bit không liên tiếp nào:

Suy nghĩ ban đầu của tôi (chúng ta sẽ thấy trong một phút làm thế nào điều này không hoạt động tốt) là bạn có thể làm tốt hơn: Nếu bạn muốn trích xuất nbit, bạn sẽ có một xung đột khi trích xuất / dịch chuyển bit inếu bạn có bất kỳ ai (không -liên tục với bit i) trong các i-1bit trước hoặc n-ibit tiếp theo.

Tôi sẽ đưa ra một vài ví dụ để minh họa:

...a..b...c...Hoạt động (không có ai trong 2 bit sau a, bit trước và bit sau bvà không ai ở 2 bit trước c):

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

...a.b....c...Thất bại vì bnằm trong 2 bit sau a(và bị kéo vào vị trí của người khác khi chúng ta thay đổi a):

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

...a...b.c...Thất bại vì bnằm trong 2 bit trước đó c(và bị đẩy vào vị trí của người khác khi chúng ta thay đổi c):

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

...a...bc...d... Hoạt động vì các bit liên tiếp dịch chuyển cùng nhau:

  a000bc000d
+ 0bc000d000
+ 000d000000
= abcd000000

Nhưng chúng tôi có một vấn đề. Nếu chúng ta sử dụng n-ithay vì n-1chúng ta có thể có kịch bản sau đây: nếu chúng ta có một vụ va chạm bên ngoài phần mà chúng ta quan tâm, thì cuối cùng chúng ta sẽ che giấu điều gì, nhưng những bit mang cuối cùng lại can thiệp vào phạm vi không che dấu quan trọng ? (và lưu ý: n-1yêu cầu đảm bảo điều này không xảy ra bằng cách đảm bảo các i-1bit sau phạm vi không che của chúng ta rõ ràng khi chúng ta dịch chuyển ibit thứ)

...a...b..c...d...Thất bại tiềm tàng đối với các bit carry, cn-1sau b, nhưng đáp ứng n-icác tiêu chí:

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

Vậy tại sao chúng ta không quay lại n-1yêu cầu " bit of space" đó? Bởi vì chúng ta có thể làm tốt hơn :

...a....b..c...d.. Thất bại trong n-1bài kiểm tra " bit of space", nhưng hoạt động cho thủ thuật trích xuất bit của chúng tôi:

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

Tôi không thể đưa ra một cách hay để mô tả các trường khôngn-1khoảng trống giữa các bit quan trọng, nhưng vẫn hoạt động cho hoạt động của chúng tôi. Tuy nhiên, vì chúng tôi biết trước các bit mà chúng tôi quan tâm, chúng tôi có thể kiểm tra bộ lọc của mình để đảm bảo chúng tôi không gặp phải các va chạm mang theo bit:

So sánh (-1 AND mask) * shiftvới kết quả tất cả những gì được mong đợi, -1 << (64-n)(đối với 64 bit không dấu)

Sự thay đổi / nhân ma thuật để trích xuất các bit của chúng tôi hoạt động khi và chỉ khi hai phần tử bằng nhau.


Tôi thích nó - bạn đúng rằng với mỗi bit, bạn chỉ cần có nhiều số không ở bên phải của nó vì bạn cần không gian cho các bit cần đến đó. Nhưng ngoài ra , nó cần nhiều bit ở bên trái vì nó có các bit kết quả ở bên trái. Vì vậy, nếu một bit bkết thúc ở vị trí mcủa nnó, thì nó cần phải có m-1số không ở bên trái và n-m-1số không ở bên phải. Đặc biệt là khi các bit không theo cùng thứ tự trong số ban đầu như sau khi sắp xếp lại, đây là một cải tiến quan trọng đối với các tiêu chí ban đầu. Đây là niềm vui
Floris

13

Ngoài những câu trả lời tuyệt vời cho câu hỏi rất thú vị này, có thể hữu ích khi biết rằng thủ thuật nhân bit bit này đã được biết đến trong cộng đồng cờ vua máy tính từ năm 2007, nơi nó có tên là Magic BitBoards .

Nhiều công cụ cờ vua máy tính sử dụng một số số nguyên 64 bit (được gọi là bảng bit) để thể hiện các bộ mảnh khác nhau (1 bit cho mỗi ô vuông chiếm). Giả sử một mảnh trượt (rook, giám mục, nữ hoàng) trên một hình vuông gốc nhất định có thể di chuyển đến hầu hết các Kô vuông nếu không có mảnh chặn nào xuất hiện. Sử dụng bitwise - và của các Kbit phân tán đó với bảng bit của các ô vuông bị chiếm dụng sẽ tạo ra một từ có tỷ lệ cụ thể Kđược nhúng trong một số nguyên 64 bit.

Phép nhân có thể được sử dụng để ánh xạ các Kbit phân tán này đến các Kbit thấp hơn của số nguyên 64 bit. Các Kbit thấp hơn này sau đó có thể được sử dụng để lập chỉ mục một bảng các bitcoin được tính toán trước đại diện cho các ô vuông được phép mà mảnh trên hình vuông gốc của nó thực sự có thể di chuyển đến (chăm sóc các miếng chặn, v.v.)

Một công cụ cờ thông thường sử dụng phương pháp này có 2 bàn (một cho rooks, một cho giám mục, nữ hoàng sử dụng kết hợp cả hai) 64 mục (một cho mỗi ô vuông gốc) có chứa kết quả được tính toán trước đó. Cả hai nguồn đóng được đánh giá cao nhất ( Houdini ) và công cụ cờ vua nguồn mở ( Stockfish ) hiện đang sử dụng phương pháp này cho hiệu suất rất cao.

Việc tìm các số nhân ma thuật này được thực hiện bằng cách sử dụng một tìm kiếm toàn diện (được tối ưu hóa với các lần cắt đầu) hoặc với bản dùng thử và erorr (ví dụ: thử nhiều số nguyên 64 bit ngẫu nhiên). Không có mẫu bit nào được sử dụng trong quá trình tạo di chuyển mà không tìm thấy hằng số ma thuật. Tuy nhiên, hiệu ứng mang theo bitwise thường là cần thiết khi các bit được ánh xạ có (gần như) các chỉ số liền kề.

AFAIK, phương pháp giải SAT rất chung của @Syzygy đã không được sử dụng trong cờ vua máy tính và dường như không có bất kỳ lý thuyết chính thức nào về sự tồn tại và tính độc đáo của các hằng số ma thuật như vậy.


Tôi đã nghĩ rằng bất cứ ai có nền tảng CS chính thức toàn diện đều sẽ nhảy vào phương pháp SAT ngay khi nhìn thấy vấn đề này. Có lẽ người CS thấy cờ vua không thú vị? :(
Phục hồi Monica

@KubaOber Chủ yếu là cách khác: cờ vua máy tính bị chi phối bởi những người chơi theo kiểu bit, lập trình bằng C hoặc lắp ráp, và ghét bất kỳ loại trừu tượng nào (C ++, mẫu, OO). Tôi nghĩ điều đó làm cho những kẻ CS thực sự sợ hãi :-)
TemplateRex
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.