2013-03-18 6 views
12

मेरे पास 0 और 67600 के बीच की संख्याओं की एक लंबी सूची है। अब मैं उन्हें एक सरणी का उपयोग करके स्टोर करना चाहता हूं जो 67600 तत्व लंबा है। यदि कोई सेट सेट में था तो एक तत्व 1 पर सेट किया गया है और यदि सेट सेट में नहीं है तो यह 0 पर सेट है। अर्थात। प्रत्येक बार मुझे किसी संख्या की उपस्थिति को संग्रहीत करने के लिए केवल 1 बिट जानकारी की आवश्यकता होती है। क्या सी/सी ++ में कोई हैक है जो मुझे यह प्राप्त करने में मदद करता है?सी थोड़ा सा स्टोर करने के लिए हैक जो 1 बिट स्पेस लेता है?

+3

यदि आपको केवल '67600' तत्वों की आवश्यकता है तो आपको किसी भी चाल का उपयोग नहीं करना चाहिए। यह इतना याद नहीं है। – cnicutar

+0

मुझे न्यूनतम संभव स्मृति उपयोग चाहिए। –

+9

'std :: वेक्टर ' या 'std :: बिटसेट 'का उपयोग करें। मैं उन्हें "हैक्स" नहीं कहूंगा, हालांकि –

उत्तर

15

C++ में आप std::vector<bool> उपयोग कर सकते हैं आकार गतिशील है (यह std::vector का एक विशेष मामला है, this देखें) अन्यथा वहाँ std::bitset (std::bitset यदि संभव हो तो पसंद करते हैं।) आप सेट/आकार बदलने की जरूरत है, तो भी नहीं है boost::dynamic_bitset चलने के समय पर। आप here पर जानकारी पा सकते हैं, यह बहुत अच्छा है!

सी (और सी ++) में आप मैन्युअल बिटवाइज़ ऑपरेटर्स के साथ इस लागू कर सकते हैं। सामान्य परिचालनों का एक अच्छा सारांश here है। एक बात जो मैं उल्लेख करना चाहता हूं वह है कि जब आप थोड़ा परिचालन कर रहे हों तो हस्ताक्षर किए गए पूर्णांक का उपयोग करना एक अच्छा विचार है। नकारात्मक पूर्णांक स्थानांतरित करते समय << और >> अपरिभाषित हैं। आपको uint32_t जैसे कुछ अभिन्न प्रकार के सरणी आवंटित करने की आवश्यकता होगी। यदि आप N बिट्स स्टोर करना चाहते हैं, तो इन uint32_t एस में N/32 लगेगा। बिट ii % 32 'i/32' वें uint32_t के वें बिट में संग्रहीत है। आप अपने आर्किटेक्चर और अन्य बाधाओं के आधार पर एक अलग आकार के अभिन्न प्रकार का उपयोग करना चाह सकते हैं। नोट: किसी मौजूदा कार्यान्वयन का उपयोग कर पसंद करते हैं अपने स्वयं के (रोलिंग से अधिक (जैसे सी ++ के लिए पहले पैराग्राफ में वर्णित है, गूगल सी समाधान के लिए खोज) जब तक आप विशेष रूप से करने के लिए, जिस स्थिति में मैं से बाइनरी/सा हेरफेर के बारे में जानने का सुझाव देते हैं चाहते हैं इसे सुलझाने से पहले कहीं और।) इस तरह की चीज मौत के लिए किया गया है और "अच्छे" समाधान हैं।

ऐसी कई चालें हैं जो शायद केवल एक बिट का उपभोग करें: उदा। बिटफील्ड के सरणी (सी में भी लागू), लेकिन कम जगह का उपयोग किया जाता है संकलक तक है। this link देखें। अगर आप 7 बिट्स हैं: आपके कंप्यूटर बहुत संभावना कम से कम 8 बिट आवंटित नहीं कर सकता -

कृपया ध्यान दें कि आप जो कुछ भी करते हैं, आप सूचना के एन बिट्स स्टोर करने के लिए बिल्कुल एन बिट का उपयोग करने में सक्षम हो लगभग निश्चित रूप से कभी नहीं होगा आपको 1 बिट बर्बाद करना होगा, और यदि आप 9 चाहते हैं तो आपको 16 बिट्स लेना होगा और उनमें से 7 को बर्बाद करना होगा। भले ही आपका कंप्यूटर (सीपीयू + रैम इत्यादि) एकल बिट्स पर "काम" कर सके, यदि आप malloc/new के साथ ओएस में चल रहे हैं तो यह आपके आवंटक के लिए ओवरहेड के कारण डेटा को ट्रैक करने के लिए सचेत नहीं होगा । यही कारण है कि पिछले योग्यता बहुत मूर्खतापूर्ण था - आप उपयोग में एक वास्तुकला कि आप एक समय मुझे लगता है :)

+4

विकिपीडिया लिंक बहुत अच्छा है, सिवाय इसके कि यह मुझे नहीं बताता कि मैं कितने आकार 2^67600 का प्रतिनिधित्व करता हूं। –

+0

आपको एक से अधिक पूर्णांक का उपयोग करने की आवश्यकता होगी। यदि आप अपने आधार के रूप में 'uint32_t' का उपयोग कर रहे हैं तो आपको उनमें से' NUM_OF_BITS/32' की आवश्यकता होगी और इंडेक्स करने के लिए आप 'i/32'th int पर जाएंगे और इसकी' i% 32' बिट देखेंगे। –

+0

क्या आप कृपया बता सकते हैं कि uint32_t द्वारा आपका क्या मतलब है। इसके अलावा, अगर मैं सही सोच रहा हूं, तो आप 32 के कारक द्वारा थोड़ा उपयोग घटा सकते हैं। तो उस मामले में भी 67600/32 = 2113 बहुत बड़ा है। सी में –

6

वहाँ वास्तव में है पर कम से कम 8 बिट पर संचालित करने के लिए अनुमति देता है नहीं मिलेगा! std::vector<bool> इस के लिए एक विशेषज्ञता है: http://en.cppreference.com/w/cpp/container/vector_bool

दस्तावेज़ देखें, यह इसे यथासंभव कुशलतापूर्वक संग्रहीत करता है।

संपादित करें: के रूप में किसी और ने कहा, std::bitset भी उपलब्ध है: http://en.cppreference.com/w/cpp/utility/bitset

+7

और हर कोई अब इस पर खेद करता है। –

+0

हां, इसके लिए दस्तावेज़ पढ़ना, यह वास्तव में ऐसा करने के लिए "डोडी" लगता है। 'std :: बिटसेट 'ज्यादातर मामलों में बेहतर समाधान की तरह लगता है। मैं वास्तव में कल्पना करने के लिए चिल्लाता हूं कि किस मामले में आपके पास गतिशील संख्याएं होंगी जिन्हें पूछताछ की आवश्यकता है, क्योंकि यह वास्तव में वास्तव में अजीब हो सकता है। –

+0

'boost :: dynamic_bitset' भी है। –

10

आप std::bitset उपयोग करना चाहिए।

std::bitset कार्यों bool की एक सरणी की तरह (वास्तव में std::array की तरह है, क्योंकि यह मान द्वारा प्रतियां), लेकिन केवल प्रत्येक तत्व के लिए भंडारण की 1 बिट का उपयोग करता है।

  • यह धीमी सूचक अविवेक और ढेर मेमोरी का उपयोग करता आकार बदलने सक्षम करने के लिए है, जो आप की जरूरत नहीं है:

    एक अन्य विकल्प vector<bool>, जो मैं क्योंकि अनुशंसा नहीं करते है।

  • उस प्रकार को अक्सर मानक-शुद्धवादियों द्वारा खराब किया जाता है क्योंकि यह मानक कंटेनर होने का दावा करता है, लेकिन मानक कंटेनर * की परिभाषा का पालन करने में विफल रहता है।

* उदाहरण के लिए, एक मानक अनुरूप समारोह &container.front() किसी भी कंटेनर प्रकार है, जो std::vector<bool> के साथ विफल हो के पहले तत्व के लिए सूचक का उत्पादन करने की उम्मीद कर सकता। शायद आपके उपयोग के मामले के लिए एक नाइटपिक, लेकिन अभी भी इसके बारे में जानने लायक है।

+0

कौन सा परिस्थितियों में बेहतर है, 'बिट्ससेट' या 'वेक्टर '? –

+1

@JanDvorak: बिट्ससेट! –

+1

@JanDvorak: 'बिटसेट' अगर आकार संकलन समय पर जाना जाता है (लेकिन अगर यह बहुत बड़ा है तो इसे ढेर पर डालने के बारे में सावधान रहें); 'वेक्टर ' यदि यह गतिशील है। –

4

यदि आप इसे सी में लिखना चाहते हैं, तो लंबाई में 67601 बिट्स (67601/8 = 8451) है और फिर प्रत्येक मान के लिए उचित बिट चालू/बंद करें।

+0

मेरे पास 67600 बिट्स की मेमोरी सीमा है। –

+0

मान * 0 से 67600 * हैं, इसलिए यह 67601 तत्व या 8451 वर्णों की सरणी है। – Mike

+1

@NikunjBanka - इस मामले में आप संभवतः इस कार्यक्रम को किसी भी भाषा में नहीं लिख सकते हैं। – KevinDTimm

1

दूसरों ने सही विचार दिया है। यहां bitsarr, या बिट्स की 'सरणी' का अपना कार्यान्वयन है। एक हस्ताक्षरित चार एक बाइट है, इसलिए यह अनिवार्य रूप से हस्ताक्षरित वर्णों की एक सरणी है जो व्यक्तिगत बिट्स में जानकारी संग्रहीत करता है। मैंने एक बिट मान के अलावा दो या चार बिट मानों को संग्रहीत करने का विकल्प जोड़ा, क्योंकि वे दोनों 8 (बाइट का आकार) विभाजित करते हैं, और उपयोगी होंगे यदि आप बड़ी संख्या में पूर्णांक स्टोर करना चाहते हैं जो 0 से लेकर होंगे -3 या 0-15।

सेटिंग और प्राप्त करते समय, गणित कार्यों में किया जाता है, इसलिए आप इसे एक इंडेक्स दे सकते हैं जैसे कि यह एक सामान्य सरणी था - यह जानता है कि कहां देखना है।

इसके अलावा, यह उपयोगकर्ता की ज़िम्मेदारी है कि यह निर्धारित करने के लिए मूल्य पास न करें, या यह अन्य मूल्यों को खराब कर देगा। इसे संशोधित किया जा सकता है ताकि ओवरफ्लो 0 पर वापस आ जाए, लेकिन इससे इसे और अधिक गड़बड़ कर दिया जाएगा, इसलिए मैंने खुद पर भरोसा करने का फैसला किया।

#include<stdio.h> 
#include <stdlib.h> 
#define BYTE 8 

typedef enum {ONE=1, TWO=2, FOUR=4} numbits; 

typedef struct bitsarr{ 
    unsigned char* buckets; 
    numbits n; 
} bitsarr; 


bitsarr new_bitsarr(int size, numbits n) 
{ 
    int b = sizeof(unsigned char)*BYTE; 
    int numbuckets = (size*n + b - 1)/b; 
    bitsarr ret; 
    ret.buckets = malloc(sizeof(ret.buckets)*numbuckets); 
    ret.n = n; 
    return ret; 
} 
void bitsarr_delete(bitsarr xp) 
{ 
    free(xp.buckets); 
} 

void bitsarr_set(bitsarr *xp, int index, int value) 
{ 
    int buckdex, innerdex; 
    buckdex = index/(BYTE/xp->n); 
    innerdex = index%(BYTE/xp->n); 
    xp->buckets[buckdex] = (value << innerdex*xp->n) | ((~(((1 << xp->n) - 1) << innerdex*xp->n)) & xp->buckets[buckdex]); 

    //longer version 

    /*unsigned int width, width_in_place, zeros, old, newbits, new; 
    width = (1 << xp->n) - 1; 
    width_in_place = width << innerdex*xp->n; 
    zeros = ~width_in_place; 
    old = xp->buckets[buckdex]; 
    old = old & zeros; 
    newbits = value << innerdex*xp->n; 
    new = newbits | old; 
    xp->buckets[buckdex] = new; */ 

} 

int bitsarr_get(bitsarr *xp, int index) 
{ 
    int buckdex, innerdex; 
    buckdex = index/(BYTE/xp->n); 
    innerdex = index%(BYTE/xp->n); 
    return ((((1 << xp->n) - 1) << innerdex*xp->n) & (xp->buckets[buckdex])) >> innerdex*xp->n; 

    //longer version 

    /*unsigned int width = (1 << xp->n) - 1; 
    unsigned int width_in_place = width << innerdex*xp->n; 
    unsigned int val = xp->buckets[buckdex]; 
    unsigned int retshifted = width_in_place & val; 
    unsigned int ret = retshifted >> innerdex*xp->n; 
    return ret; */ 
} 

int main() 
{ 
    bitsarr x = new_bitsarr(100, FOUR); 
    for(int i = 0; i<16; i++) 
     bitsarr_set(&x, i, i); 
    for(int i = 0; i<16; i++) 
     printf("%d\n", bitsarr_get(&x, i)); 
    for(int i = 0; i<16; i++) 
     bitsarr_set(&x, i, 15-i); 
    for(int i = 0; i<16; i++) 
     printf("%d\n", bitsarr_get(&x, i)); 
    bitsarr_delete(x); 
} 
संबंधित मुद्दे