2012-02-13 18 views
5

में 0 -बहुत पहले उपयोगी है जब आपके आकार की आवश्यकताओं का कोई अंदाजा नहीं है। क्या किसी को MATLAB में एरे आवंटित करने के लिए एक समान विधि के बारे में पता है?MATLAB à la std :: वेक्टर :: आरक्षित (एन)

मैं वास्तव में निम्नलिखित की तरह hacky (लेकिन प्रभावी) तरीकों में कोई दिलचस्पी नहीं हूँ:

x = zeros(1000,1); 
for i = 1:10000 
    if i > numel(x) 
     x = [x;zeros(size(x))]; 
    end 
    x(i) = rand; 
end 
x(i+1:end) = []; 
+2

आपको यह उत्तर उपयोगी हो सकता है: http://stackoverflow.com/a/1549094/97160 – Amro

+0

@Amro: हाँ, हमेशा के रूप में महान जवाब । लेकिन मैं उम्मीद कर रहा था कि कुछ "जादू" MATLAB फ़ंक्शन था जिसे मैंने अनदेखा किया था। – Jacob

उत्तर

3

"hacky" जिस तरह से यह करने के लिए एक ही रास्ता है। हालांकि, आपको < = numel (x) की जांच करने की आवश्यकता नहीं है। सरणी का विस्तार अपने रहेगी (लेकिन सरणी के बिना दोहरीकरण):

x = zeros(1000,1); 
for i = 1:10000 
    x(i) = rand; 
end 
x(i+1:end) = []; 

संपादित करें: करने के लिए यह सरल रखने, जबकि अभी भी बनाए रखना सरणी दोहरीकरण, आप एक वर्ग, या बस कुछ सहायक कार्यों (नीचे) लिख सकते हैं।

EDIT2: सहायक कार्यों का उपयोग मैन्युअल हैक की तुलना में चीजों को धीमा कर देगा। MATLAB 2010 में यह अभी भी निष्क्रिय विकास से बहुत तेज है। MATLAB 2011 में निष्पक्ष दृष्टिकोण वास्तव में तेज़ है, यह सुझाव देता है कि इस संस्करण में स्मार्ट आवंटन है। शायद यह काफी तेज़ है ताकि कोई भी हैक की आवश्यकता न हो। एंड्रयू जंक के लिए यह इंगित करने के लिए धन्यवाद।

function listtest() 
    n = 10000; 
    l = new_list(); 
    for i=1:n 
     l = list_append(l, i); 
    end 
    a = list_to_array(l); 
end 

function l = new_list() 
    l = [0 0]; 
end 
function l = list_append(l, e) 
    if l(1)+1 == length(l) 
     l(length(l)*2) = 0; 
    end 
    l(1) = l(1)+1; 
    l(l(1)+1) = e; 
end 
function a = list_to_array(l) 
    a = l(2:1+l(1)); 
end 

संपादित करें (AndrewJanke से)

यहाँ कार्यान्वयन की गति की तुलना कोड है।

function manual_reserve_example(n) 
x = zeros(1000,1); 
for i = 1:n 
    if i > numel(x) 
     x = [x;zeros(size(x))]; 
    end 
    x(i) = i; 
end 
x(i+1:end) = []; 
end 

function naive_growth(n) 
x = 0; 
for i = 1:n 
    x(i) = i; 
end 
end 

function compare_them(n) 
fprintf('Doing %d elements in Matlab R%s\n', n, version('-release')); 
tic; 
naive_growth(n); 
fprintf('%30s %.6f sec\n', 'naive_growth', toc); 
tic; 
manual_reserve_example(n); 
fprintf('%30s %.6f sec\n', 'manual_reserve', toc); 
tic; 
listtest(n); 
fprintf('%30s %.6f sec\n', 'listtest', toc); 
end 
+2

मूल प्रश्न में चेक ने ओवरफ्लो पर आवंटन आकार को दोगुना करने के लिए एक एल्गोरिदम लागू किया, जिसके परिणामस्वरूप 'ओ (लॉग (एन))' पुनर्वितरण (इस मामले में 4)। इस उदाहरण में 9 000 पुनर्वितरण के लिए, मैटलैब का प्राकृतिक विकास केवल एक समय में एक तत्व बढ़ता है। – Pursuit

+0

@ पीछा: बिल्कुल। यह वही है जो 'आरक्षित 'करता है। – Jacob

+0

rasmus: -1 नहीं। फ़ंक्शन कॉल ओवरहेड (और जेआईटी के इन-प्लेस ऑप्टिमाइज़ेशन की संभावित हार) इस सहायक कार्य कार्यान्वयन को जैकब के मैन्युअल विस्तार से भी धीमा कर देती है, या यहां तक ​​कि बेवकूफ गैर-प्रीलोकेटेड 'x = 0; मैं = 1: एन के लिए; एक्स (i) = मैं; अंत 'कोड। क्या आपने इसका परीक्षण किया? Matlab में, और उस मामले के लिए अन्य भाषाओं में, आपको संचालन की लागत पर विचार करने की आवश्यकता है और वास्तव में आपके द्वारा विचार किए जाने वाले कोड के प्रदर्शन को मापने की आवश्यकता है। उच्च ओवरहेड के कारण कक्षा बनाना भी बदतर होगा। –

0

MATLAB 7.6 (R2008a) में एक संरचना के लिए स्मृति preallocate को struct और REPMAT आदेशों का उपयोग कर एक तरीका नहीं है।

उदाहरण 1: एक उप क्षेत्र

s.field1.subfield के साथ एक क्षेत्र के साथ एक संरचना: दो क्षेत्रों

s.field1 s.field2

s = struct('field1',cell(1),'field2',cell(1)); 

उदाहरण 2 के साथ एक संरचना

s = struct('field1',struct('subfield',cell(1))); 

उदाहरण 3: संरचनाओं की एक सरणी

वी (1) .field1 ... वी (100) .field1

s = struct('field1',cell(1)); 
v = repmat(s,100,1); 
+0

यह काम नहीं करता है। 'Wh' के साथ आवंटित बाइट्स की संख्या को' whos v' के साथ देखें जब आप इसमें डेटा जोड़ते हैं; यह पूर्व आवंटित नहीं है। जैसे 'whos v; v (1) .field1 = 10; whos v; v (2) .field1 = 20; whos v' – Jacob

1

उदाहरण है कि आपके द्वारा प्रदान किए साफ समाधान पीछे की ओर को दोहराना।

for i = 10000:-1:1 
    x(i) = rand; 
end 

इस मामले हैं, जहां अंत आकार वास्तव में अज्ञात है में काम नहीं करता है, लेकिन यह मेरे लिए काम में अधिक बार की तुलना में मैं उम्मीद होता आ गया है।


अन्यथा मैं आमतौर पर मूल प्रश्न में दिखाए जाने वाले "ओवरफ्लो पर डबल" एल्गोरिदम लागू करता हूं।

स्वच्छ समाधान एक मैटलैब कक्षा को एक सम्मानित वेक्टर आकार बदलने वाले एल्गोरिदम के चारों ओर लपेटना है, और उसके बाद उस वर्ग का उपयोग करें। मुझे किसी भी कारण से अवगत नहीं है कि इस तरह के वर्ग का निर्माण नहीं किया जा सका, लेकिन मैंने वास्तव में कभी बैठे और एक को लागू करने की कोशिश नहीं की।(मुझे उत्सुकता है कि फ़ाइल एक्सचेंज पर कहीं भी एक उदाहरण मौजूद है।)

+0

कुछ कार्यान्वयन यहां @woodchips द्वारा सुझाए गए थे: http://stackoverflow.com/a/3251547/ 97,160 – Amro

संबंधित मुद्दे