एकल गुणन के साथ बिट्स निकालना


301

मैं एक में इस्तेमाल एक दिलचस्प तकनीक देखा जवाब करने के लिए एक और सवाल है, और यह समझने के लिए थोड़ा बेहतर करना चाहते हैं।

हमें 64-बिट पूर्णांक दिया गया है, और हम निम्नलिखित बिट्स में रुचि रखते हैं:

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

विशेष रूप से, हम उन्हें शीर्ष आठ स्थानों पर ले जाना चाहते हैं, जैसे:

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

हम संकेतित बिट्स के मूल्य के बारे में परवाह नहीं करते हैं ., और उन्हें संरक्षित करने की आवश्यकता नहीं है।

समाधान अवांछित बिट्स बाहर मुखौटा, और द्वारा परिणाम गुणा करने के लिए था 0x2040810204081। यह, जैसा कि यह निकला, चाल करता है।

यह विधि कितनी सामान्य है? क्या बिट्स के किसी भी सबसेट को निकालने के लिए इस तकनीक का उपयोग किया जा सकता है? यदि नहीं, तो एक बिट के विशेष सेट के लिए विधि कैसे काम करती है या नहीं, यह कैसे पता चलता है?

अंत में, किसी दिए गए बिट्स को निकालने के लिए (a?) सही गुणक को खोजने के बारे में कैसे जाना जाएगा?


29
यदि आपने पाया कि एक दिलचस्प है, तो इस सूची पर एक नज़र डालें: graphics.stanford.edu/~seander/bithacks.html उनमें से बहुत सारे (ab) रोचक परिणाम प्राप्त करने के लिए एक व्यापक-पूर्णांक गुणन / विभाजन का उपयोग करते हैं। ("4 ऑपरेशन के साथ एक बाइट में बिट्स को उल्टा करें" भाग दिखाता है कि बिटशिफ्ट / गुणन चाल से कैसे निपटें जब आपके पास पर्याप्त स्थान नहीं है और दो बार मास्क / गुणा करने की आवश्यकता है)
viraptor

@viraptor: उत्कृष्ट बिंदु। यदि आप इस पद्धति की सीमाओं को समझते हैं, तो आप बिट हेरफेर के संबंध में बहुत कुछ हासिल करने के लिए वास्तव में गुणा का उपयोग कर सकते हैं।
एक्सपेडिटो

9
तो दिलचस्प बात यह है कि
AVX2

3
चालाक बिट twiddling एल्गोरिदम के लिए देखो करने के लिए एक और जगह है एमआईटी HAKMEM
Barmar

1
उम लिवरो कोन्हेको सोबरे ओ अस्सुंतो (ई गोस्टो बास्टांटे) Del ओ "हैकर डिलाइट" लिंक
सेलेस

जवाबों:


235

बहुत दिलचस्प सवाल, और चालाक चाल।

आइए एक एकल बाइट में हेरफेर करने के एक सरल उदाहरण को देखें। सरलता के लिए अहस्ताक्षरित 8 बिट का उपयोग करना। कल्पना कीजिए कि आपका नंबर है xxaxxbxxऔर आप चाहते हैं ab000000

समाधान में दो चरण शामिल थे: थोड़ा सा मास्किंग, उसके बाद गुणन। बिट मास्क एक सरल और ऑपरेशन है जो निर्बाध बिट्स को शून्य में बदल देता है। उपरोक्त मामले में, आपका मुखौटा 00100100और परिणाम होगा 00a00b00

अब कठिन हिस्सा: में बदल रहा है ab......

गुणन शिफ्ट-एंड-ऐड ऑपरेशन का एक गुच्छा है। कुंजी ओवरफ्लो को "दूर हटने" की अनुमति देने की है, बिट्स की हमें ज़रूरत नहीं है और जिन्हें हम चाहते हैं उन्हें सही जगह पर रखें।

4 से गुणा ( 00000100) 2 के द्वारा छोड़ी गई सभी चीजों को शिफ्ट कर देगा और आपको प्राप्त करेगा a00b0000। प्राप्त करने के लिए bऊपर ले जाने के हम 1 से गुणा करने के लिए (सही जगह में एक रखने के लिए) 4 (ख ऊपर ले जाने के) की जरूरत है। यह योग 5 है, और पहले के 4 के साथ संयुक्त होकर हमें 20 या एक जादुई संख्या मिलती है 00010100। मूल 00a00b00मास्किंग के बाद था ; गुणन देता है:

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

इस दृष्टिकोण से आप बड़ी संख्या और अधिक बिट्स तक बढ़ा सकते हैं।

आपके द्वारा पूछे गए प्रश्नों में से एक था "क्या यह किसी भी संख्या में बिट्स के साथ किया जा सकता है?" मुझे लगता है कि उत्तर "नहीं" है, जब तक कि आप कई मास्किंग ऑपरेशन या कई गुणा की अनुमति नहीं देते हैं। समस्या "टकराव" का मुद्दा है - उदाहरण के लिए, ऊपर की समस्या में "आवारा बी"। कल्पना कीजिए कि हमें इस तरह की संख्या के लिए ऐसा करने की आवश्यकता है xaxxbxxcx। पहले के दृष्टिकोण के बाद, आपको लगता है कि हमें {x 2, x {1 + 4 + 16}} = x 42 (oooh - हर चीज का जवाब!) चाहिए। परिणाम:

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

जैसा कि आप देख सकते हैं, यह अभी भी काम करता है, लेकिन "केवल"। वे यहाँ कुंजी यह है कि बिट्स के बीच "पर्याप्त जगह" है जो हम चाहते हैं कि हम सब कुछ निचोड़ सकते हैं। मैं ग के बाद एक चौथाई बिट डी नहीं जोड़ सका, क्योंकि मुझे ऐसे उदाहरण मिलेंगे जहां मुझे सी + डी मिलता है, बिट्स ले जा सकता है, ...

तो औपचारिक प्रमाण के बिना, मैं आपके प्रश्न के अधिक दिलचस्प भागों का उत्तर निम्नानुसार दूंगा: "नहीं, यह किसी भी संख्या में बिट्स के लिए काम नहीं करेगा। एन बिट्स निकालने के लिए, आपको बिट्स के बीच रिक्त स्थान (एन -1) की आवश्यकता होती है। अतिरिक्त मास्क लगाएं, या निकालें। "

एकमात्र अपवाद मैं "बिट्स (एन -1) बिट्स के बीच शून्य" के लिए सोच सकता हूं, यह नियम है: यदि आप दो बिट्स निकालना चाहते हैं जो मूल में एक दूसरे से सटे हैं, और आप उन्हें रखना चाहते हैं उसी क्रम में, फिर भी आप कर सकते हैं। और (N-1) नियम के उद्देश्य के लिए वे दो बिट्स के रूप में गिने जाते हैं।

एक और अंतर्दृष्टि है - नीचे दिए गए @Ternary के उत्तर से प्रेरित है (मेरी टिप्पणी देखें)। प्रत्येक दिलचस्प बिट के लिए, आपको इसके सही भाग के लिए केवल उतने ही शून्य की आवश्यकता है जितनी आपको बिट्स के लिए जगह की आवश्यकता होती है जो वहां जाने की आवश्यकता होती है। लेकिन यह भी, यह बाईं ओर के रूप में कई बिट्स की जरूरत है क्योंकि यह बाईं ओर परिणाम बिट्स है। इसलिए यदि थोड़ा b n की स्थिति में समाप्त होता है, तो इसके दाईं ओर m-1 शून्य होना चाहिए, और इसके दाईं ओर nm शून्य होना चाहिए। विशेष रूप से जब बिट्स मूल संख्या में समान क्रम में नहीं होते हैं जैसा कि वे पुन: आदेश देने के बाद होंगे, यह मूल मानदंडों में एक महत्वपूर्ण सुधार है। इसका मतलब है, उदाहरण के लिए, कि एक 16 बिट शब्द

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

में शिफ्ट किया जा सकता है

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

भले ही ई और बी के बीच केवल एक स्थान है, दो डी और सी के बीच, तीन अन्य के बीच। N-1 को जो भी हुआ ?? इस मामले में, a...e"एक ब्लॉक" बन जाता है - उन्हें सही स्थान पर 1 से गुणा करने के लिए गुणा किया जाता है, और इसलिए "हमें मुफ्त में ई मिला"। बी और डी के लिए एक ही सही है (बी को दाईं ओर तीन रिक्त स्थान की आवश्यकता है, डी को इसके बाईं ओर तीन की आवश्यकता है)। इसलिए जब हम जादू की संख्या की गणना करते हैं, तो हम पाते हैं कि डुप्लिकेट हैं:

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

स्पष्ट रूप से, यदि आप इन नंबरों को एक अलग क्रम में चाहते हैं, तो आपको उन्हें आगे रखना होगा। हम (N-1)नियम में सुधार कर सकते हैं : "यह हमेशा काम करेगा यदि बिट्स के बीच कम से कम (एन -1) रिक्त स्थान हैं, या, यदि अंतिम परिणाम में बिट्स का क्रम ज्ञात है, तो यदि स्थिति बी में स्थिति बी थोड़ा समाप्त हो जाती है n, इसके बाईं ओर m-1 शून्य और इसके दाईं ओर nm शून्य होना आवश्यक है। "

@ टर्नेरी ने बताया कि यह नियम काफी काम नहीं करता है, क्योंकि बिट्स से एक कैरी जोड़ा जा सकता है "बस लक्ष्य क्षेत्र के दाईं ओर" - जब हम जिस बिट की तलाश कर रहे हैं वे सभी हैं। उदाहरण को जारी रखते हुए मैंने 16 बिट शब्द में पाँच कसकर भरे हुए बिट्स के साथ ऊपर दिया: यदि हम साथ शुरू करते हैं

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

सादगी के लिए, मैं थोड़ा पदों का नाम दूंगा ABCDEFGHIJKLMNOP

हम जो गणित करने जा रहे थे, वह था

ABCDEFGHIJKLMNOP

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

अब तक, हमने सोचा था कि नीचे कुछ भी abcde(स्थिति ABCDE) कोई फर्क नहीं पड़ेगा, लेकिन वास्तव में, जैसा कि @Ternary ने बताया है, अगर b=1, c=1, d=1तब (b+c)स्थिति में स्थिति Gको ले जाने के लिए थोड़ा कारण होगा F, जिसका अर्थ है कि (d+1)स्थिति Fमें थोड़ा सा ले जाएगा E- और हमारे रिजल्ट खराब हुआ ध्यान दें कि ब्याज के कम से कम महत्वपूर्ण बिट के स्थान पर ( cइस उदाहरण में) कोई फर्क नहीं पड़ता, क्योंकि गुणन कम से कम महत्वपूर्ण बिट से ज़ोनोस के साथ पैडिंग का कारण होगा।

इसलिए हमें अपने (एम -1) / (एनएम) नियम को संशोधित करने की आवश्यकता है। यदि एक से अधिक बिट है जिसमें "बिल्कुल (nm) अप्रयुक्त बिट्स दाईं ओर है (पैटर्न में अंतिम बिट की गिनती नहीं है - ऊपर उदाहरण में" c "), तो हमें नियम को मजबूत करने की आवश्यकता है - और हमें करना होगा ऐसा करने के लिए!

हमें न केवल उन बिट्स की संख्या को देखना होगा जो (nm) कसौटी पर खरे उतरते हैं, बल्कि वे भी हैं जो (n-m + 1) आदि हैं, आइए उनकी संख्या Q0 (ठीक n-mअगले बिट तक), Q1 को कॉल करें ( n-m + 1), Q (N-1) (n-1) तक। फिर हम जोखिम उठाते हैं यदि

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

यदि आप इसे देखते हैं, तो आप देख सकते हैं कि यदि आप एक सरल गणितीय अभिव्यक्ति लिखते हैं

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

और परिणाम यह है W > 2 * N, तो आपको आरएचएस मानदंड को एक बिट तक बढ़ाने की आवश्यकता है (n-m+1)। इस बिंदु पर, जब तक ऑपरेशन सुरक्षित है W < 4; यदि वह काम नहीं करता है, तो मानदंड को एक और बढ़ाएं, आदि।

मुझे लगता है कि उपरोक्त का अनुसरण करने से आपको अपने उत्तर के लिए एक लंबा रास्ता मिल जाएगा ...


1
महान। एक और अधिक सूक्ष्म समस्या: कै-बिट्स के कारण m-1 / nm परीक्षण कुछ समय के लिए विफल हो जाता है। एक प्रयास करें ... b..c ... d - आप पाँचवीं बिट में b + c के साथ हवा देते हैं, यदि वे दोनों 1 एक कैरी बिट बनाते हैं, जो clobbers d (!)
Ternary

1
upshot: n-1 बिट्स ऑफ़ स्पेस फॉरबिड कॉन्फ़िगरेशन जो काम करना चाहिए (iea ... b..c ... d), और m-1 / nm उन लोगों को अनुमति देता है जो काम नहीं करते (a ... b..c ... घ)। मैं काम करने के लिए एक सरल तरीके के साथ नहीं आ पाया हूं जो काम करेगा और जो नहीं करेगा।
टर्निरी

तुम अच्छे हो! कैरी की समस्या का अर्थ है कि हमें "सुरक्षा" के रूप में प्रत्येक बिट के दाईं ओर थोड़ा और स्थान चाहिए। पहली नज़र में, अगर कम से कम दो बिट्स हैं, जो दाईं ओर न्यूनतम एनएम हैं, तो आपको अंतरिक्ष को 1 से बढ़ाना होगा। आम तौर पर, यदि पी ऐसे बिट्स हैं, तो आपको लॉग 2 (पी) अतिरिक्त बिट्स की आवश्यकता है किसी का भी अधिकार जिसमें न्यूनतम (mn) था। आपको सही लगता है?
फ्लोरिस

खैर वह अंतिम टिप्पणी बहुत सरल थी। मुझे लगता है कि मेरा सबसे हाल ही में संपादित उत्तर दिखाता है कि log2 (P) सही दृष्टिकोण नहीं है। @ टेरनेरी का अपना जवाब (नीचे) बहुत ही शानदार तरीके से दिखाता है कि कैसे आप किसी विशेष बिट संयोजन के लिए बता सकते हैं यदि आपके पास कोई गारंटीकृत समाधान नहीं है - मेरा मानना ​​है कि ऊपर दिए गए कार्य कुछ और हैं।
फ्लोरिस

1
यह शायद एक संयोग है, लेकिन इस उत्तर को तब स्वीकार किया गया, जब उत्थान की संख्या 127 तक पहुंच गई। अगर आपने इसे दूर तक पढ़ा है, तो आप मेरे साथ मुस्कुराएंगे ...
फ्लोरिस

154

बहुत दिलचस्प सवाल वास्तव में। मैं अपने दो सेंटों के साथ चीम कर रहा हूं, जो यह है कि, यदि आप बिटवॉटर सिद्धांत पर पहले-क्रम तर्क के संदर्भ में इस तरह की समस्याओं का प्रबंधन कर सकते हैं, तो प्रमेय साबित करने वाला आपका दोस्त है, और संभवतः आपको बहुत तेजी से प्रदान कर सकता है आपके सवालों के जवाब। आइए एक प्रमेय के रूप में पूछी जा रही समस्या को फिर से बताएं:

"कुछ 64-बिट स्थिरांक 'मास्क' और 'गुणक' मौजूद है, जैसे कि सभी 64-बिट बिटवेक्टर x के लिए, अभिव्यक्ति y = (x & mask) * गुणक में, हमारे पास वह y.63 == x.63 है , y.62 == x.55, y.61 == x.47, आदि "

यदि यह वाक्य वास्तव में एक प्रमेय है, तो यह सच है कि स्थिरांक 'मास्क' और 'गुणक' के कुछ मूल्य इस संपत्ति को संतुष्ट करते हैं। तो आइए इसे कुछ के संदर्भ में वाक्यांश दें, जो एक प्रमेय कहावत को समझ सकता है, अर्थात् श्रीमती-एलआईबी 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)

और अब आइए प्रमेय से पूछें Z3 कि क्या यह प्रमेय है:

z3.exe /m /smt2 ExtractBitsThroughAndWithMultiplication.smt2

परिणाम है:

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

बिंगो! यह मूल पद में दिए गए परिणाम को 0.06 सेकंड में पुन: पेश करता है।

अधिक सामान्य दृष्टिकोण से इसे देखते हुए, हम इसे प्रथम-क्रम कार्यक्रम संश्लेषण समस्या का एक उदाहरण के रूप में देख सकते हैं, जो कि शोध का एक नवजात क्षेत्र है जिसके बारे में कुछ शोधपत्र प्रकाशित हुए हैं। आपके लिए एक खोज "program synthesis" filetype:pdfशुरू होनी चाहिए।


2
मैं प्रभावित हु! मुझे नहीं पता था कि "बिटवेक्टर सिद्धांत पर प्रथम-क्रम तर्क" यहां तक ​​कि लोगों द्वारा अध्ययन किया गया एक वास्तविक विषय था - अकेले चलो कि यह इस तरह के दिलचस्प परिणाम दे सकता है। इसे साझा करने के लिए बहुत - बहुत धन्यवाद।
फ्लोरिस

@AndrewBacker: क्या कोई मुझे बता सकता है कि इस तथाकथित "SO-as-a-job" चीज का क्या मतलब है? मेरा मतलब है, यह कुछ भी भुगतान नहीं करता है । आप एसओ रेप पर अकेले नहीं रह सकते। हो सकता है कि यह आपको साक्षात्कार में कुछ बिंदु दे सके। शायद। यदि कार्यस्थल एसओ प्रतिनिधि के मूल्य को पहचानने के लिए पर्याप्त है, और यह एक दिया नहीं है ...
मोनिका

3
ज़रूर। बहुत सारे लोगों के लिए SO भी एक खेल है (अंकों के साथ कुछ भी)। बस इंसानी स्वभाव, जैसे शिकार / आर / नया ताकि आप पहली टिप्पणी पोस्ट कर सकें और कर्म पा सकें। इसके बारे में कुछ भी बुरा नहीं है, जब तक कि उत्तर अभी भी अच्छे हैं। मैं किसी के समय और प्रयास को बढ़ाने में सक्षम होने के लिए खुश हूं जब वे वास्तव में ध्यान दें कि किसी ने किया था। प्रोत्साहन अच्छा सामान है :) और ... यह एक बहुत पुरानी टिप्पणी थी, और अभी भी सच है। मैं नहीं देखता कि यह कैसे स्पष्ट नहीं है।
एंड्रयू बैकर

88

गुणक में प्रत्येक 1-बिट का उपयोग बिट्स में से एक को उसकी सही स्थिति में कॉपी करने के लिए किया जाता है:

  • 1पहले से ही सही स्थिति में है, इसलिए इससे गुणा करें 0x0000000000000001
  • 27 बिट स्थिति को बाईं ओर स्थानांतरित किया जाना चाहिए, इसलिए हम 0x0000000000000080(बिट 7 सेट है) से गुणा करें ।
  • 314 बिट स्थिति को बाईं ओर स्थानांतरित किया जाना चाहिए, इसलिए हम 0x0000000000000400(बिट 14 सेट है) से गुणा करें ।
  • और तब तक
  • 849 बिट पदों को बाईं ओर स्थानांतरित किया जाना चाहिए, इसलिए हम 0x0002000000000000(बिट 49 सेट है) से गुणा करें ।

गुणक व्यक्तिगत बिट्स के लिए गुणक का योग है।

यह केवल इसलिए काम करता है क्योंकि एकत्र किए जाने वाले बिट्स एक साथ बहुत करीब नहीं होते हैं, ताकि बिट्स का गुणन जो हमारी योजना में एक साथ नहीं होता है या तो 64 बिट से नीचे या निचले डोन्ट-केयर भाग से परे हो।

ध्यान दें कि मूल संख्या में अन्य बिट्स होना चाहिए 0। यह उन्हें AND और ऑपरेशन से मास्क करके प्राप्त किया जा सकता है।


2
महान व्याख्या! आपके संक्षिप्त उत्तर ने "मैजिक नंबर" के मूल्य को जल्दी से ढूंढना संभव बना दिया।
एक्सपेडिटो

4
यह वास्तव में सबसे अच्छा जवाब है, लेकिन यह पहले (फ्लोरिस के उत्तर) के पढ़ने (पहली छमाही) के बिना इतना मददगार नहीं होता।
एंड्रयू बैकर

29

(मैंने पहले कभी नहीं देखा था। यह चाल बहुत अच्छी है!)

मैं फ्लोरिस के दावे पर थोड़ा विस्तार करूंगा कि जब nबिट्स को निकालते हैं तो आपको n-1किसी भी गैर-निरंतर बिट्स के बीच जगह की आवश्यकता होती है:

मेरा प्रारंभिक विचार (हम एक मिनट में देखेंगे कि यह कैसे काम नहीं करता है) यह था कि आप बेहतर कर सकते हैं: यदि आप nबिट्स को निकालना चाहते हैं , iतो आपके पास किसी को भी निकालने या शिफ्ट करने पर टकराव होगा (यदि आप किसी के पास हैं तो बिट के साथ -consecutive iमें) i-1बिट्स ठीक पहले या n-iबाद में बिट्स।

मैं उदाहरण के लिए कुछ उदाहरण दूंगा:

...a..b...c...काम करता है (2 बिट में कोई भी नहीं है a, पहले थोड़ा और बाद में b, और कोई भी 2 बिट में नहीं है c):

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

...a.b....c...असफल होने के bबाद 2 बिट्स में है a(और जब हम शिफ्ट होते हैं तो किसी और की जगह पर खींचा जाता है a):

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

...a...b.c...क्योंकि b2 बिट्स में पूर्ववर्ती है c(और जब हम शिफ्ट होते हैं तो किसी और के स्थान पर धकेल दिया जाता है c):

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

...a...bc...d... काम करता है क्योंकि लगातार बिट्स एक साथ बदलते हैं:

  a000bc000d
+ 0bc000d000
+ 000d000000
= abcd000000

लेकिन हमें एक समस्या है। यदि हम n-iइसके बजाय उपयोग n-1करते हैं तो हमारे पास निम्न परिदृश्य हो सकते हैं: क्या होगा यदि हमारे पास उस हिस्से के बाहर एक टकराव है जिसकी हम परवाह करते हैं, कुछ जिसे हम अंत में दूर कर देते हैं, लेकिन जिनके कैरी बिट्स अंत में महत्वपूर्ण संयुक्त राष्ट्र के नकाबपोश रेंज में हस्तक्षेप करते हैं ? (और ध्यान दें: n-1आवश्यकता यकीन है कि यह बनाकर नहीं होता है सुनिश्चित करता है कि i-1बिट्स हमारे अन-नकाबपोश सीमा के बाद स्पष्ट हैं जब हम बदलाव iवें बिट)

...a...b..c...d...कैरी-बिट पर संभावित विफलता, cमें है n-1के बाद b, लेकिन संतुष्ट n-iमापदंड:

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

तो क्यों न हम बस उस " n-1बिट्स ऑफ़ स्पेस" आवश्यकता पर वापस जाएं ? क्योंकि हम बेहतर कर सकते हैं :

...a....b..c...d.. " n-1बिट्स ऑफ़ स्पेस" परीक्षण में विफल रहता है , लेकिन हमारी बिट-एक्सट्रैक्शन चाल के लिए काम करता है :

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

मैं इन क्षेत्रों को चिह्नित करने के लिए एक अच्छा तरीका नहीं ला सकता हूं जिसमें महत्वपूर्ण बिट्स के बीच जगह नहीं है n-1, लेकिन फिर भी हमारे ऑपरेशन के लिए काम करेंगे। हालाँकि, जब से हम समय से पहले जानते हैं कि हम किस बिट में रुचि रखते हैं हम अपने फ़िल्टर की जाँच कर सकते हैं ताकि हम सुनिश्चित कर सकें कि हम कैरी-बिट टकराव का अनुभव न करें:

(-1 AND mask) * shiftअपेक्षित सभी के विरुद्ध परिणाम की तुलना करें , -1 << (64-n)(64-बिट अहस्ताक्षरित के लिए)

हमारे बिट्स निकालने के लिए जादू की पारी / गुणा अगर और केवल दो समान हैं तो काम करता है।


मुझे यह पसंद है - आप सही हैं कि प्रत्येक बिट के लिए, आपको केवल इसके लिए बहुत सारे शून्य की आवश्यकता है क्योंकि आपको बिट्स के लिए जगह की आवश्यकता है जो वहां जाने की आवश्यकता है। लेकिन यह भी , यह बाईं ओर के रूप में कई बिट्स की जरूरत है क्योंकि यह बाईं ओर परिणाम बिट्स है। इसलिए यदि थोड़ा सा bऊपर की स्थिति में समाप्त होता mहै n, तो उसे m-1इसके बाईं ओर n-m-1शून्य और इसके दाईं ओर शून्य होना आवश्यक है। विशेष रूप से जब बिट्स मूल संख्या में समान क्रम में नहीं होते हैं जैसा कि वे फिर से आदेश देने के बाद होगा, यह मूल मानदंडों में एक महत्वपूर्ण सुधार है। यह मजेदार है।
फ्लोरिस

13

इस बहुत ही दिलचस्प सवाल के पहले से ही उत्कृष्ट जवाब के अलावा, यह जानना उपयोगी हो सकता है कि यह बिटवाइज़ गुणा चाल 2007 के बाद से कंप्यूटर शतरंज समुदाय में जानी जाती है, जहां यह मैजिक बिटबॉर्ड्स के नाम से जाना जाता है ।

कई कंप्यूटर शतरंज इंजन कई 64-बिट पूर्णांक (जिन्हें बिटबोर्ड कहा जाता है) का उपयोग विभिन्न टुकड़ा सेटों (प्रति कब्जा वर्ग के 1 बिट) का प्रतिनिधित्व करने के लिए करते हैं। मान लीजिए कि एक निश्चित मूल वर्ग पर एक फिसलने वाला टुकड़ा (बदमाश, बिशप, रानी) सबसे Kचौकों पर जा सकता है अगर कोई अवरुद्ध टुकड़े मौजूद नहीं थे। Kकब्जे वाले वर्गों के बिटबोर्ड के साथ बिटवेट -और उन बिखरे हुए बिट्स का उपयोग करना K64-बिट पूर्णांक के भीतर एम्बेडेड एक विशिष्ट- शब्द देता है ।

64-बिट पूर्णांक Kके निचले Kबिट्स में इन बिखरे हुए बिट्स को मैप करने के लिए मैजिक गुणा का उपयोग किया जा सकता है । Kफिर इन निचले बिट्स का उपयोग पूर्व-गणना किए गए बिटबोर्ड की एक तालिका को अनुक्रमित करने के लिए किया जा सकता है जो अनुमत वर्गों का प्रतिनिधित्व करता है कि इसके मूल वर्ग पर टुकड़ा वास्तव में स्थानांतरित हो सकता है (अवरुद्ध टुकड़ों आदि की देखभाल करना)

इस दृष्टिकोण का उपयोग करने वाले एक विशिष्ट शतरंज इंजन में 64 प्रविष्टियों (एक प्रति वर्ग) के दोनों तालिकाओं (रस्सियों के लिए एक, बिशप के लिए एक, दोनों के संयोजन का उपयोग करके एक) है जिसमें ऐसे पूर्व-गणना परिणाम होते हैं। दोनों उच्चतम रेट बंद स्रोत ( हूडिनी ) और खुला स्रोत शतरंज इंजन ( सूखी हुई मछली ) वर्तमान में अपने बहुत ही उच्च प्रदर्शन के लिए इस दृष्टिकोण का उपयोग।

इन मैजिक मल्टीप्लायरों को ढूंढना या तो एक्सक्लूसिव सर्च (शुरुआती कटऑफ के साथ अनुकूलित) या ट्रायल और एरो के साथ किया जाता है (जैसे यादृच्छिक 64-बिट पूर्णांकों की बहुत कोशिश करना)। चाल पीढ़ी के दौरान कोई बिट पैटर्न का उपयोग नहीं किया गया है जिसके लिए कोई जादू निरंतर नहीं पाया जा सकता है। हालाँकि, बिट-ले जाने के प्रभाव आमतौर पर आवश्यक होते हैं जब टू-मैप मैप बिट्स (लगभग) आसन्न सूचक होते हैं।

AFAIK, @Syzygy द्वारा बहुत सामान्य SAT-solver दृष्टिकोण का उपयोग कंप्यूटर शतरंज में नहीं किया गया है, और न ही इस तरह के जादू स्थिरांक के अस्तित्व और विशिष्टता के बारे में कोई औपचारिक सिद्धांत प्रतीत होता है।


मैंने सोचा होगा कि जिस किसी के पास फुल-फॉमल फॉर्मल CS बैकग्राउंड है, वह इस समस्या को देखकर सीधे SAT दृष्टिकोण में कूद जाएगा। शायद सीएस लोगों को शतरंज निर्बाध लगता है? :(
मोनिका

@ क्यूबाओबर यह ज्यादातर अन्य तरीकों से होता है: कंप्यूटर शतरंज में बिट-ट्विडलर्स का प्रभुत्व होता है जो C या असेंबली में प्रोग्राम करते हैं, और किसी भी तरह के एब्सट्रैक्शन (C ++, टेम्पलेट्स, OO) से घृणा करते हैं। मुझे लगता है कि असली सीएस लोगों को डराता है :-)
TemplateRex
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.