2012-02-22 31 views
7

प्रारंभिक संख्या को देखते हुए, अपने लगातार हिस्सों के अनंत अनुक्रम की कल्पना करें।लगातार हिस्सों के अनंत अनुक्रम के लिए लिंक कथन

1, 0.5, 0.25, 0.125, ... 

(double में निहित किसी भी संख्यात्मक अस्थायित्व पर ध्यान न दें।)

इस किसी भी कस्टम विस्तार तरीकों या जनरेटर तरीकों लेखन के बिना एक भी अभिव्यक्ति में किया जा सकता है?

+4

क्यों मनमाने ढंग से प्रतिबंध? क्या यह होमवर्क है? यदि आप अपनी व्यक्त सीमाओं के प्रति प्रतिबद्ध नहीं हैं, तो बस 'उपज' 'वापसी 'का उपयोग करके एक पुनरावर्तक लिखें। –

+5

अनंत अनुक्रम और कंप्यूटर एक साथ काम नहीं करते हैं। –

+6

@Ramhound निश्चित रूप से वे करते हैं, जब तक आप सभी वस्तुओं को प्राप्त करने की कोशिश नहीं करते हैं। – hvd

उत्तर

10

मैं एक एकल अभिव्यक्ति रास्ते से पता नहीं है, लेकिन मैं यहाँ इस चालाक जनरेटर कोड मिला: http://csharpindepth.com/articles/Chapter11/StreamingAndIterators.aspx

public static IEnumerable<TSource> Generate<TSource>(TSource start, 
                Func<TSource,TSource> step) 
{ 
    TSource current = start; 
    while (true) 
    { 
     yield return current; 
     current = step(current); 
    } 
} 

आपके मामले में आप इसका उपयोग:

foreach (double d in Generate<double>(1, c => c/2)) 
{ 
    ... 
} 
2
Enumerable.Repeat(1, int.MaxValue).Select((x, i) => x/Math.Pow(2, i)) 

यह वास्तव में अनंत नहीं है, लेकिन Repeat और Select दोनों स्थगित निष्पादन का उपयोग करते हैं, तो आप कोई प्रदर्शन नहीं खोलेंगे।

अनंत linq अभिव्यक्ति बनाने के लिए कोई मूल तरीका नहीं पता।

या आप मैन्युअल रूप से .Repeat

10

मस्ती के लिए की अनंत संस्करण लिख सकते हैं, यहां एक भी अभिव्यक्ति में एक वास्तविक अनंत अनुक्रम बनाने के लिए एक चाल है। पहली दो परिभाषा वर्ग फ़ील्ड हैं, ताकि उन्हें अभिव्यक्ति के लिए अभिव्यक्ति की आवश्यकता न हो।

double? helper; 
IEnumerable<double> infinite; 

infinite = new object[] { null }.SelectMany(dummy => new double[] { (helper = (helper/2) ?? 1).Value }.Concat(infinite)); 
+1

यह बहुत अच्छा है, एक भयानक तरीके से :) –

+1

मैंने इसे किसी अन्य चीज़ के रूप में नहीं बनाया था :) – hvd

+2

कूल। आप इसे लिंककैड में समझा सकते हैं लेकिन किसी कारण से यह क्रैश हो जाता है यदि आप उस पर एक गणना() करने का प्रयास करते हैं; o) –

0

मुझे सीधे LINQ के साथ अनंत अनुक्रम बनाने के किसी भी तरीके से नहीं पता है। हालांकि, आप बहुत लंबे अनुक्रम बना सकते हैं।

var sequence = Enumerable.Range(0, int.MaxValue) 
         .Select(n => Math.Pow(2, -n)); 

हालांकि, बाद से double परिमित सटीक है, तो आप शायद लेकिन शून्य कुछ भी नहीं मिलेगा n बहुत अधिक हो जाता है के बाद। क्या होता है यह देखने के लिए आपको प्रयोग करना होगा, और इससे पहले कि n कितना उच्च हो सके।

3

यहाँ एक जवाब प्रदान की एक @hvd के समान है, लेकिन का उपयोग कर Y ऑपरेटर परिभाषित here, इस स्थानीय चर के लिए की जरूरत को हटा:

public static Func<A, R> Y<A, R>(Func<Func<A, R>, Func<A, R>> f) 
{ 
    return t => f(Y(f))(t); 
} 

var halves = Y<double, IEnumerable<double>>(self => d => new[] { 0d }.SelectMany(_ => new[] { d }.Concat(self(d/2)))); 

एक उदाहरण उपयोग होगा:

foreach (var half in halves(20)) 
    Console.WriteLine(half); 

कौन सा होगा उत्पादन 20, 10, 5, 2.5 आदि ...

मैं उत्पादन कोड में इस का उपयोग करते हुए सलाह नहीं होगा, लेकिन यह मजेदार है।

Y ऑपरेटर भी अनुमति देता है अन्य पुनरावर्ती लैम्ब्डा अभिव्यक्ति, उदाहरण के लिए:

var fibonacci = Y<int, int>(self => n => n > 1 ? self(n - 1) + self(n - 2) : n); 
var factorial = Y<int, int>(self => n => n > 1 ? n * self(n - 1) : n); 
var hanoi = Y<int, int>(self => n => n == 1 ? 1 : 2 * self(n - 1) + 1); 
+0

यह साफ है। यह दो अभिव्यक्तियों का उपयोग करता है, लेकिन यह संभव है कि 'वाई' फ़ंक्शन पहले ही परिभाषित किया गया हो, इस स्थिति में आप इसका संदर्भ दे सकते हैं और इसकी परिभाषा से बच सकते हैं। – hvd