यह समझा जा रहा है कि सबसे खराब स्थिति यह है O(N)
, कुछ बहुत अच्छे सूक्ष्म अनुकूलन हैं।
भोली विधि एक चरित्र तुलना और प्रत्येक चरित्र के लिए एक पाठ की तुलना करती है।
एक प्रहरी का उपयोग करना (यानी पाठ के अंत में लक्ष्य चरित्र की एक प्रति) का उपयोग करके प्रति वर्ण की तुलना की संख्या कम हो जाती है।
बिट ट्विडलिंग स्तर पर है:
#define haszero(v) ( ((v) - 0x01010101UL) & ~(v) & 0x80808080UL )
#define hasvalue(x, n) ( haszero((x) ^ (~0UL / 255 * (n))) )
यह जानने के लिए कि किसी शब्द में किसी बाइट x
का कोई विशिष्ट मान है ( n
)।
v - 0x01010101UL
जब भी संबंधित बाइट v
शून्य या उससे अधिक होती है , तो सबफ़्रेशन , किसी भी बाइट में एक उच्च बिट सेट का मूल्यांकन करता है 0x80
।
उप-अभिव्यक्ति ~v & 0x80808080UL
बाइट्स में सेट किए गए उच्च बिट्स का मूल्यांकन करती है जहां बाइट का v
अपना उच्च बिट सेट नहीं है (इसलिए बाइट से कम था0x80
)।
इन दो उप-अभिव्यक्तियों को क्रमबद्ध करके ( haszero
परिणाम) उच्च बिट्स सेट है जहां बाइट v
शून्य में थे, क्योंकि उच्च बिट्स एक मान से अधिक होने के कारण सेट होते हैं0x80
पहले उप अभिव्यक्ति में दूसरा द्वारा बंद से छुपाया जाता है (27 अप्रैल, 1987 एलन माईक्रॉफ्ट द्वारा)।
अब हम x
उस शब्द के साथ परीक्षण के लिए XOR ( ) कर सकते हैं जो बाइट मान के साथ भरा गया है जिसमें हम रुचि रखते हैं ( n
)। क्योंकि ज़ीरो बाइट और नॉनज़ेरो में अपने आप में एक मूल्य होने के कारण, हम परिणाम को पास कर सकते हैं haszero
।
इस बार एक ठेठ में प्रयोग किया जाता है strchr
कार्यान्वयन।
(स्टीफन एम बेनेट ने 13 दिसंबर 2009 को यह सुझाव दिया था। प्रसिद्ध बिट ट्विडलिंग हैक्स में आगे का विवरण )।
पुनश्च
यह कोड किसी के 1111
बगल में किसी भी संयोजन के लिए टूट गया है0
हैक जानवर बल परीक्षण पास करता है (बस धैर्य रखें):
#include <iostream>
#include <limits>
bool haszero(std::uint32_t v)
{
return (v - std::uint32_t(0x01010101)) & ~v & std::uint32_t(0x80808080);
}
bool hasvalue(std::uint32_t x, unsigned char n)
{
return haszero(x ^ (~std::uint32_t(0) / 255 * n));
}
bool hasvalue_slow(std::uint32_t x, unsigned char n)
{
for (unsigned i(0); i < 32; i += 8)
if (((x >> i) & 0xFF) == n)
return true;
return false;
}
int main()
{
const std::uint64_t stop(std::numeric_limits<std::uint32_t>::max());
for (unsigned c(0); c < 256; ++c)
{
std::cout << "Testing " << c << std::endl;
for (std::uint64_t w(0); w != stop; ++w)
{
if (w && w % 100000000 == 0)
std::cout << w * 100 / stop << "%\r" << std::flush;
const bool h(hasvalue(w, c));
const bool hs(hasvalue_slow(w, c));
if (h != hs)
std::cerr << "hasvalue(" << w << ',' << c << ") is " << h << '\n';
}
}
return 0;
}
एक उत्तर के लिए बहुत सारे उत्थान जो धारणा बनाता है एक करारा बैक्टीरिया = एक बाइट, जो आजकल मानक से अधिक नहीं है
टिप्पणी के लिए धन्यवाद।
जवाब कुछ भी हो सकता था, लेकिन मल्टी-बाइट / वैरिएबल-चौड़ाई एन्कोडिंग्स पर एक निबंध :-) (सभी निष्पक्षता में जो मेरी विशेषज्ञता का क्षेत्र नहीं है और मुझे यकीन नहीं है कि यह ओपी देख रहा था)।
वैसे भी यह मुझे लगता है कि उपरोक्त विचारों / चालों को कुछ हद तक MBE के लिए अनुकूलित किया जा सकता है (विशेषकर सेल्फ-सिंकिंग एन्कोडिंग ):
- जैसा कि जोहान की टिप्पणी में उल्लेख किया गया है कि हैक को आसानी से डबल बाइट्स या किसी भी चीज़ के लिए बढ़ाया जा सकता है (निश्चित रूप से आप इसे बहुत ज्यादा नहीं बढ़ा सकते हैं);
- एक विशिष्ट फ़ंक्शन जो एक मल्टीबाइट कैरेक्टर स्ट्रिंग में एक वर्ण का पता लगाता है:
- प्रहरी तकनीक का उपयोग थोड़ी दूरदर्शिता के साथ किया जा सकता है।