2011-04-28 15 views
26

में गॉसियन (आमतौर पर वितरित) यादृच्छिक संख्या उत्पन्न करने के लिए कोड रूबी में सामान्य रूप से वितरित यादृच्छिक संख्या उत्पन्न करने के लिए कुछ कोड क्या है?रूबी

(नोट: मैं अपने ही सवाल का जवाब है, लेकिन मैं अगर कोई एक बेहतर जवाब है देखने के लिए स्वीकार करने से पहले कुछ दिनों के इंतजार करेंगे।)

संपादित करें:

इस के लिए सर्च कर रहे हैं, मैं

+ "सामान्य वितरण" माणिक

और

: अतः दो खोजों से उत्पन्न पर सभी पृष्ठों को देखा

+ गाऊसी + यादृच्छिक माणिक

+0

क्या आपका चेक संबंधित प्रश्न था (दाएं तरफ पैनल देखें)? – Gumbo

+0

हां, मैंने जांच की और यद्यपि ऐसे स्थान हैं जिनमें एल्गोरिदम है, किसी ने इसे रूबी में कोड नहीं किया है। यह एक आम काम है कि यह वास्तव में मानक पुस्तकालय में होना चाहिए। लेकिन उसमें असफल रहा, मुझे लगता है कि कॉपी-पेस्ट कोड StackOverflow पर खोजने योग्य होना चाहिए। – Eponymous

+0

आपके द्वारा चेक की गई चीज़ों का उल्लेख करना एक अच्छा विचार हो सकता है, ताकि लोग उत्तर देने के बारे में सोच सकें, जब तक उन्हें लगता है कि आप कुछ याद नहीं करते हैं। –

उत्तर

43

पायथन के random.gauss() और बूस्ट के normal_distribution दोनों Box-Muller transform उपयोग करते हैं, तो वह भी रूबी के लिए काफी अच्छा होना चाहिए।

def gaussian(mean, stddev, rand) 
    theta = 2 * Math::PI * rand.call 
    rho = Math.sqrt(-2 * Math.log(1 - rand.call)) 
    scale = stddev * rho 
    x = mean + scale * Math.cos(theta) 
    y = mean + scale * Math.sin(theta) 
    return x, y 
end 

विधि को उस वर्ग में लपेटा जा सकता है जो नमूनों को एक-एक करके लौटाता है।

class RandomGaussian 
    def initialize(mean, stddev, rand_helper = lambda { Kernel.rand }) 
    @rand_helper = rand_helper 
    @mean = mean 
    @stddev = stddev 
    @valid = false 
    @next = 0 
    end 

    def rand 
    if @valid then 
     @valid = false 
     return @next 
    else 
     @valid = true 
     x, y = self.class.gaussian(@mean, @stddev, @rand_helper) 
     @next = y 
     return x 
    end 
    end 

    private 
    def self.gaussian(mean, stddev, rand) 
    theta = 2 * Math::PI * rand.call 
    rho = Math.sqrt(-2 * Math.log(1 - rand.call)) 
    scale = stddev * rho 
    x = mean + scale * Math.cos(theta) 
    y = mean + scale * Math.sin(theta) 
    return x, y 
    end 
end 

CC0(CC0)

संभव सीमा कानून के तहत करने के लिए

, antonakosRandomGaussian रूबी वर्ग के लिए सभी कॉपीराइट और संबंधित या पड़ोसी अधिकार माफ कर दी गई है। यह काम डेनमार्क से प्रकाशित है।


लाइसेंस विवरण का मतलब यह नहीं है कि मुझे इस कोड की परवाह है। इसके विपरीत, मैं कोड का उपयोग नहीं करता, मैंने इसका परीक्षण नहीं किया है, और मैं रूबी में प्रोग्राम नहीं करता हूं।

+0

क्या आप अपने कोड (बीएसडी/सीसी -0 या कुछ ऐसे) पर एक अनुमोदित लाइसेंस जोड़ सकते हैं (क्योंकि यह कट-पेस्ट पुन: उपयोग के लिए है) – Eponymous

+4

@ एपोनिनाम हो गया। – antonakos

+2

सिग ब्लॉक के लिए सिर्फ वोट दिया गया;) – drewish

19

मूल प्रश्न कोड के लिए पूछा गया, लेकिन लेखक की अनुवर्ती टिप्पणी ने मौजूदा पुस्तकालयों का उपयोग करने में रुचि दिखाई। मुझे इसमें दिलचस्पी थी, और मेरी खोजों ने इन दो रूबी रत्नों को बदल दिया:

gsl - "जीएनयू वैज्ञानिक पुस्तकालय में रूबी इंटरफेस" (आपको जीएसएल स्थापित करने की आवश्यकता है)। "PHPMath से आँकड़े पुस्तकालयों के एक बंदरगाह" (शुद्ध रूबी) - मतलब = 0 और किसी दिए गए मानक विचलन के साथ सामान्य रूप से वितरित यादृच्छिक संख्या के लिए बुला अनुक्रम

rng = GSL::Rng.alloc 
rng.gaussian(sd)  # a single random sample 
rng.gaussian(sd, 100) # 100 random samples 

rubystats है। दिए गए माध्य और मानक विचलन के साथ सामान्य रूप से वितरित यादृच्छिक संख्याओं के लिए कॉलिंग अनुक्रम

gen = Rubystats::NormalDistribution.new(mean, sd) 
gen.rng    # a single random sample 
gen.rng(100)   # 100 random samples 
10

+1 @ एंटोनकोस के उत्तर पर +1 है। यहां बॉक्स-मुलर का कार्यान्वयन है जिसका मैं उपयोग कर रहा हूं; यह अनिवार्य रूप से समान है, लेकिन थोड़ा तंग कोड:

class RandomGaussian 
    def initialize(mean = 0.0, sd = 1.0, rng = lambda { Kernel.rand }) 
    @mean, @sd, @rng = mean, sd, rng 
    @compute_next_pair = false 
    end 

    def rand 
    if (@compute_next_pair = [email protected]_next_pair) 
     # Compute a pair of random values with normal distribution. 
     # See http://en.wikipedia.org/wiki/Box-Muller_transform 
     theta = 2 * Math::PI * @rng.call 
     scale = @sd * Math.sqrt(-2 * Math.log(1 - @rng.call)) 
     @g1 = @mean + scale * Math.sin(theta) 
     @g0 = @mean + scale * Math.cos(theta) 
    else 
     @g1 
    end 
    end 
end 
बेशक

, यदि आप वास्तव में गति के बारे में परवाह है, तो आप को लागू करना चाहिए Ziggurat Algorithm :)।

8

एक और विकल्प, यह distribution मणि का उपयोग कर रहा है, जो साइब्रू फेलो में से एक द्वारा लिखित है।

यह सोचने के लिए थोड़ा आसान है, मुझे लगता है।

require 'distribution' 
normal = Distribution::Normal.rng(1) 
norm_distribution = 1_000.times.map {normal.call} 
+0

इस कोड को देखते हुए, मुझे नहीं पता कि अपेक्षित मानक विचलन क्या होना चाहिए। –

+1

यहां जाएं: http://rubydoc.info/gems/distribution/0.7.0/Distribution/Normal/Ruby_ आप देखेंगे कि आरएनजी (1) माध्य निर्दिष्ट कर रहा है, और आप मानक विचलन निर्दिष्ट कर सकते हैं आप अतिरिक्त पैरामीटर 'वितरण :: Normal.rng (माध्य, standard_deviation)' को पारित करना चाहते हैं जिसे आप उस वितरण में यादृच्छिक मान प्रदान करने के लिए कहते हैं। – Ryanmt

+0

सही लिंक है: [वितरण] (https://rubygems.org/gems/distribution) – pisaruk