रूबी तथ्यात्मक कार्य


88

मैं पागल हो रहा हूं: गुटबाजी के लिए रूबी समारोह कहां है? नहीं, मुझे ट्यूटोरियल कार्यान्वयन की आवश्यकता नहीं है, मैं सिर्फ लाइब्रेरी से फ़ंक्शन चाहता हूं। यह मठ में नहीं है!

मुझे संदेह होने लगा है, क्या यह एक मानक पुस्तकालय कार्य है?


63
मुझे यह पसंद है6.downto(1).inject(:*)
mckeed

43
@ मैके: या (1..6).inject(:*)जो थोड़ा अधिक सक्सेसफुल है।
17

8
आप एक होने की उम्मीद क्यों करेंगे?
राष्ट्रपति जेम्स के। पोल्क

4
मुझे आश्चर्य है कि रूबी के लिए गणित और विज्ञान पुस्तकालयों की स्थिति क्या है।
एंड्रयू ग्रिम

5
इंजेक्शन का उपयोग करके दिए गए उदाहरणों पर बस एक नोट। (1..num).inject(:*)जहां मामले के लिए विफल रहता है num == 0। नकारात्मक (1..(num.zero? ? 1 : num)).inject(:*)मामलों के लिए 0 केस और रिटर्न के nilलिए सही उत्तर देता है ।
योग

जवाबों:


136

मानक पुस्तकालय में कोई तथ्यात्मक कार्य नहीं है।


7
रूबी में Math.gammaविधि है, उदाहरण के लिए stackoverflow.com/a/37352690/407213
डोरियन

क्या पागल तर्क है! हमारे पास (n-1) है! समारोह और सादे n नहीं है! !!!
अलेक्जेंडर गोर्ग


77

यह मानक पुस्तकालय में नहीं है, लेकिन आप इंटेगर वर्ग का विस्तार कर सकते हैं।

class Integer
  def factorial_recursive
    self <= 1 ? 1 : self * (self - 1).factorial
  end
  def factorial_iterative
    f = 1; for i in 1..self; f *= i; end; f
  end
  alias :factorial :factorial_iterative
end

स्पष्ट प्रदर्शन कारणों के लिए NB Iterative factorial एक बेहतर विकल्प है।


8
उन्होंने स्पष्ट रूप से कहा, वह एक कार्यान्वयन नहीं चाहते हैं।
sepp2k

117
वह नहीं हो सकता है; लेकिन "रूबी फैक्टोरियल" के लिए खोज करने वाले लोग शायद।
पियरे-एंटोनी लाफेयेट

1
rosettacode.org/wiki/Factorial#Ruby सिर्फ गलत है। 0 के लिए कोई मामला नहीं है
डगलस जी। एलन

क्या पुनरावर्ती संस्करण वास्तव में धीमा है? यह इस पर निर्भर हो सकता है कि रूबी पूंछ-पुनरावर्ती अनुकूलन करता है या नहीं।
लेक्स लिंडसे

24

बेशर्मी से http://rosettacode.org/wiki/Factorial#Ruby से मेरी निजी पसंद है

class Integer
  def fact
    (1..self).reduce(:*) || 1
  end
end

>> 400.fact
=> 64034522846623895262347970319503005850702583026002959458684445942802397169186831436278478647463264676294350575035856810848298162883517435228961988646802997937341654150838162426461942352307046244325015114448670890662773914918117331955996440709549671345290477020322434911210797593280795101545372667251627877890009349763765710326350331533965349868386831339352024373788157786791506311858702618270169819740062983025308591298346162272304558339520759611505302236086810433297255194852674432232438669948422404232599805551610635942376961399231917134063858996537970147827206606320217379472010321356624613809077942304597360699567595836096158715129913822286578579549361617654480453222007825818400848436415591229454275384803558374518022675900061399560145595206127211192918105032491008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

यह कार्यान्वयन रोसेटा कोड में सूचीबद्ध वेरिएंट में सबसे तेज़ भी होता है।

अद्यतन # 1

|| 1शून्य मामले को संभालने के लिए जोड़ा गया ।

अद्यतन # 2

मार्क थॉमस के लिए धन्यवाद और प्रशंसा के साथ , यहां एक ऐसा संस्करण है जो थोड़ा अधिक कुशल, सुरुचिपूर्ण और अस्पष्ट है:

class Integer
  def fact
    (2..self).reduce(1,:*)
  end
end

1
धत, इसका क्या मतलब है?! हाँ, यह तेज़ है, लेकिन इसके बहुत ही असामान्य रूप से हालांकि
निकोलो मी।

3
यह भी 0 के लिए गलत है! - कुछ ऐसा होना चाहिए: यदि स्व <= 1; 1; अन्य; (1..self) .reduce (: *); अंत
Tarmo

8
अगर आप इसे समझ नहीं पाते हैं तो @allen - भाषा को दोष न दें। इसका सीधा सा मतलब है, सीमा 1 को स्वयं पर ले जाएं, फिर उसमें से पहला तत्व (1) हटा दें (यानी कार्यात्मक प्रोग्रामिंग में इसका मतलब कम हो जाए)। फिर जो बचा है उसका पहला तत्व (2) निकालें और उन दोनों को एक साथ गुणा करें (: *)। अब जो कुछ बचा है उसमें से पहला तत्व निकालें (3) और गुणा करें जो रनिंग टोटल के साथ है। तब तक चलते रहें, जब तक कुछ नहीं बचा (यानी आपने पूरी रेंज को संभाल लिया है)। यदि कम विफल रहता है (क्योंकि 0 के मामले में सरणी खाली है!) तो वैसे भी 1 वापस करें।
SDJMcHattie

तुम भी में प्रारंभिक मूल्य निर्दिष्ट करके शून्य मामले संभाल कर सकते हैं reduce: (1..self).reduce(1,:*)
मार्क थॉमस

3
वास्तव में आप उपयोग कर सकते हैं (2..self).reduce(1,:*), अगर सूक्ष्म दक्षता आपकी चीज है :)
मार्क थॉमस


14

आप ऐसे Math.gammaफ़ंक्शन का भी उपयोग कर सकते हैं जो पूर्णांक मापदंडों के लिए फैक्टरियल को उबालते हैं।


3
डॉक्स से: "ध्यान दें कि पूर्णांक n> 0. के लिए गामा (n) तथ्य (n-1) के समान है। हालांकि गामा (n) फ्लोट देता है और एक अनुमान हो सकता है"। यदि कोई इसे ध्यान में रखता है, तो यह काम करता है, लेकिन कम समाधान आगे बहुत अधिक सीधा लगता है।
माइकल कोहल

इसके लिए धन्यवाद! मेरी आंत कहती है कि जब भी संभव हो, एक कस्टम-लिखित कम से अधिक मानक पुस्तकालय का उपयोग करें। प्रोफाइलिंग अन्यथा सुझाव दे सकती है।
डेविड जे।

2
नोट: यह O (1) और इसके लिए सटीक है 0..22: MRI रूबी वास्तव में उन मूल्यों के लिए एक खोज करता है ( स्रोतstatic const double fact_table[] में देखें )। इसके अलावा, इसका एक अनुमान है। 23!, उदाहरण के लिए, एक 56-बिट मंटिसा की आवश्यकता होती है जो कि आईईईई 754 डबल का उपयोग करके सटीक रूप से प्रतिनिधित्व करना असंभव है जिसमें 53-बिट मंटिसा है।
fny

13
class Integer
  def !
    (1..self).inject(:*)
  end
end

उदाहरण

!3  # => 6
!4  # => 24

इसमें गलत क्या है class Integer ; def ! ; (1..self).inject(:*) ; end ; end?
अलेक्सी मटिहस्किन

@ मुदासोबवा मुझे यह पसंद है, मैंने सादगी के लिए रिफलेक्ट किया है।
जस्सोनलोहर्ड

4
मैं सम्मानपूर्वक सुझाव देना चाहता हूं कि एक सत्य विधि को वापस करने के लिए सभी रूबी वस्तुओं में शामिल एक उदाहरण विधि को ओवरराइड करने के बजाय, एक झूठा एक आपके कई दोस्तों को नहीं बना सकता है।
MatzFan

यह नकारात्मक ऑपरेटर को कुछ और बनने के लिए खतरनाक हो सकता है जब aऐसा होने Integerके मामले में कुछ और हो !a... ऐसा करने से बग का अस्तित्व हो सकता है जिसे बताना बहुत मुश्किल है। यदि aबड़ी संख्या में ऐसा होता है, 357264543तो प्रोसेसर एक बड़े लूप में जा रहा है और लोग आश्चर्यचकित हो सकते हैं कि अचानक कार्यक्रम धीमा क्यों हो जाता है
गैरबराबरी

यह जवाब उपयोग करने के लिए एक व्यावहारिक उदाहरण के बजाय साझा करने के लिए सिर्फ एक अच्छी बात थी।
जस्सोनलहार्ड


6

मैंने अभी अपना लिखा है:

def fact(n)
  if n<= 1
    1
  else
    n * fact( n - 1 )
  end
end

इसके अलावा, आप एक गिरते हुए तथ्य को परिभाषित कर सकते हैं:

def fall_fact(n,k)
  if k <= 0
    1
  else
    n*fall_fact(n - 1, k - 1)
  end
end

4

बस इस फ़ंक्शन को कॉल करें

def factorial(n=0)
  (1..n).inject(:*)
end

उदाहरण

factorial(3)
factorial(11)

3

का उपयोग करना Math.gamma.floorएक अनुमान लगाने का एक आसान तरीका है और फिर इसे वापस सही पूर्णांक परिणाम के लिए गोल करना। सभी इंटेगर के लिए काम करना चाहिए, यदि आवश्यक हो तो एक इनपुट चेक शामिल करें।


6
सुधार: इसके बाद n = 22यह सटीक उत्तर देना बंद कर देता है और सन्निकटन पैदा करता है।
अय्यार्क

2

उन सभी के लिए उच्च सम्मान के साथ जिन्होंने भाग लिया और हमारी मदद करने के लिए अपना समय बिताया, मैं यहां सूचीबद्ध समाधानों के अपने बेंचमार्क साझा करना चाहूंगा। पैरामीटर:

पुनरावृति = १०००

n = 6

                                     user     system      total        real
Math.gamma(n+1)                   0.000383   0.000106   0.000489 (  0.000487)
(1..n).inject(:*) || 1            0.003986   0.000000   0.003986 (  0.003987)
(1..n).reduce(1, :*)              0.003926   0.000000   0.003926 (  0.004023)
1.upto(n) {|x| factorial *= x }   0.003748   0.011734   0.015482 (  0.022795)

एन = 10 के लिए

  user     system      total        real
0.000378   0.000102   0.000480 (  0.000477)
0.004469   0.000007   0.004476 (  0.004491)
0.004532   0.000024   0.004556 (  0.005119)
0.027720   0.011211   0.038931 (  0.058309)

1
ध्यान देने योग्य बात यह है कि सबसे तेज Math.gamma(n+1)भी केवल n> 22 के लिए अनुमानित है, इसलिए सभी उपयोग के मामलों के लिए उपयुक्त नहीं हो सकता है।
नील स्लेटर

1

यह करने के लिए बस एक और तरीका है, हालांकि यह वास्तव में आवश्यक नहीं है।

class Factorial
   attr_reader :num
   def initialize(num)
      @num = num
   end

   def find_factorial
      (1..num).inject(:*) || 1
   end
end

number = Factorial.new(8).find_factorial
puts number

1

आपको संभवतः रूबी सुविधा अनुरोध उपयोगी लगेगा । इसमें एक nontrivial पैच शामिल है जिसमें एक डेमो बैश स्क्रिप्ट शामिल है । एक भोले पाश और बैच में प्रस्तुत समाधान के बीच की गति का अंतर शाब्दिक रूप से 100x (सौ गुना) हो सकता है। शुद्ध रूबी में सभी लिखा।


1

यहाँ मेरा संस्करण मेरे लिए स्पष्ट प्रतीत होता है भले ही यह उतना साफ न हो।

def factorial(num)
    step = 0
    (num - 1).times do (step += 1 ;num *= step) end
    return num
end

यह मेरी irb परीक्षण लाइन थी जिसमें प्रत्येक चरण दिखाया गया था।

num = 8;step = 0;(num - 1).times do (step += 1 ;num *= step; puts num) end;num

0
class Integer
  def factorial
    return self < 0 ? false : self==0 ? 1 : self.downto(1).inject(:*)
    #Not sure what other libraries say, but my understanding is that factorial of 
    #anything less than 0 does not exist.
  end
end

0

और फिर भी एक और तरीका (=)

def factorial(number)
  number = number.to_i
  number_range = (number).downto(1).to_a
  factorial = number_range.inject(:*)
  puts "The factorial of #{number} is #{factorial}"
end
factorial(#number)


0

मानक पुस्तकालय को एक तथ्यात्मक विधि की आवश्यकता क्यों होगी, जब इस सटीक उद्देश्य के लिए एक अंतर्निर्मित पुनरावृत्ति होती है? इसे कहते हैं upto

नहीं, आपको इन सभी अन्य उत्तर दिखाने की तरह, पुनरावर्तन का उपयोग करने की आवश्यकता नहीं है।

def fact(n)
  n == 0 ? 1 : n * fact(n - 1)
end  

इसके बजाय, निर्मित इट्रेटर का उपयोग फैक्टरियों की गणना करने के लिए किया जा सकता है:

factorial = 1
1.upto(10) {|x| factorial *= x }
factorial
 => 3628800
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.