यह पता चला है कि बिना किसी लूप के ऐसा करना संभव है। इस समस्या के (कम से कम) 8 बिट संस्करण को प्रीकंप्यूट करना सबसे तेज़ है। बेशक, ये टेबल कैश स्पेस का उपयोग करते हैं, लेकिन अभी भी लगभग सभी आधुनिक पीसी परिदृश्यों में नेट स्पीडअप होना चाहिए। इस कोड में, n = 0 रिटर्न कम से कम सेट बिट, एन = 1 सेकंड करने वाली कम से कम आदि
__popcnt साथ समाधान
वहाँ एक समाधान __popcnt आंतरिक उपयोग कर रहा है (आप __popcnt की जरूरत है, एक साधारण लूप समाधान पर बेहद तेज़ या किसी भी लाभ लाभ होने के लिए मंथन होगा। सौभाग्य से अधिकांश एसएसई 4 + युग प्रोसेसर इसका समर्थन करते हैं)।
// lookup table for sub-problem: 8-bit v
byte PRECOMP[256][8] = { .... } // PRECOMP[v][n] for v < 256 and n < 8
ulong nthSetBit(ulong v, ulong n) {
ulong p = __popcnt(v & 0xFFFF);
ulong shift = 0;
if (p <= n) {
v >>= 16;
shift += 16;
n -= p;
}
p = __popcnt(v & 0xFF);
if (p <= n) {
shift += 8;
v >>= 8;
n -= p;
}
if (n >= 8) return 0; // optional safety, in case n > # of set bits
return PRECOMP[v & 0xFF][n] << shift;
}
यह दर्शाता है कि कैसे विभाजित और जीत दृष्टिकोण काम करता है।
जनरल समाधान
वहाँ भी है __popcnt बिना "सामान्य" architectures- के लिए एक समाधान। यह 8-बिट भाग में प्रसंस्करण करके किया जा सकता है। आप एक और लुकअप तालिका है कि आप एक बाइट की popcnt बताता है की जरूरत है:
byte PRECOMP[256][8] = { .... } // PRECOMP[v][n] for v<256 and n < 8
byte POPCNT[256] = { ... } // POPCNT[v] is the number of set bits in v. (v < 256)
ulong nthSetBit(ulong v, ulong n) {
ulong p = POPCNT[v & 0xFF];
ulong shift = 0;
if (p <= n) {
n -= p;
v >>= 8;
shift += 8;
p = POPCNT[v & 0xFF];
if (p <= n) {
n -= p;
shift += 8;
v >>= 8;
p = POPCNT[v & 0xFF];
if (p <= n) {
n -= p;
shift += 8;
v >>= 8;
}
}
}
if (n >= 8) return 0; // optional safety, in case n > # of set bits
return PRECOMP[v & 0xFF][n] << shift;
}
यह, ज़ाहिर है, एक पाश के साथ किया जा सकता है, लेकिन unrolled प्रपत्र तेजी से होता है और लूप के असामान्य रूप में यह होगा संभावना नहीं है कि संकलक स्वचालित रूप से आपके लिए इसे अनलॉक कर सकता है।
आप एक सामान्य तरीका है जिसके आप किसी भी निरंतर n के लिए n वें सबसे कम बिट गणना करने के लिए एक रास्ता देने के लिए लागू किया जा सकता, या आप इसे क्रम में दिए गए किसी भी n के लिए काम करने की आवश्यकता है के लिए पूछ रहे हैं? मास्क-इन प्रकार के हैक्स के पैटर्न को कम करने के आधार पर, मुझे गंभीरता से संदेह है कि लूपिंग निर्माण के बिना उत्तरार्द्ध करने का एक शानदार तरीका है। –
हाँ, आप रनटाइम पर वी और एन दोनों की आपूर्ति करते हैं। मैं बिना लूपिंग के इसे करने के किसी भी तरीके से सोच नहीं सकता था। समस्या को विभाजित करना मुश्किल है, लेकिन मुझे विश्वास नहीं है कि लूप को हरा करना असंभव है। – VoidStar