Ruby factorial function

99封情书 提交于 2019-11-27 17:39:30

There is no factorial function in the standard library.

Like this is better

(1..n).inject(:*) || 1
Pierre-Antoine LaFayette

It's not in the standard library but you can extend the Integer class.

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

N.B. Iterative factorial is a better choice for obvious performance reasons.

Shamelessly cribbed from http://rosettacode.org/wiki/Factorial#Ruby, my personal favorite is

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

>> 400.fact
=> 64034522846623895262347970319503005850702583026002959458684445942802397169186831436278478647463264676294350575035856810848298162883517435228961988646802997937341654150838162426461942352307046244325015114448670890662773914918117331955996440709549671345290477020322434911210797593280795101545372667251627877890009349763765710326350331533965349868386831339352024373788157786791506311858702618270169819740062983025308591298346162272304558339520759611505302236086810433297255194852674432232438669948422404232599805551610635942376961399231917134063858996537970147827206606320217379472010321356624613809077942304597360699567595836096158715129913822286578579549361617654480453222007825818400848436415591229454275384803558374518022675900061399560145595206127211192918105032491008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

This implementation also happens to be the fastest among the variants listed in Rosetta Code.

update #1

Added || 1 to handle the zero case.

update #2

With thanks and appreciation to Mark Thomas, here's a version that is a bit more efficient, elegant and obscure:

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

You could also use Math.gamma function which boils down to factorial for integer parameters.

In math, factorial of n is just the gamma function of n+1
(see: http://en.wikipedia.org/wiki/Gamma_function)

Ruby has Math.gamma() so just use Math.gamma(n+1) and cast it back to an integer if desired.

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

examples

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

I would do

(1..n).inject(1, :*)

I just wrote my own:

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

Also, you can define a falling factorial:

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

Using Math.gamma.floor is an easy way to produce an approximation and then round it back down to the correct integer result. Should work for all Integers, include an input check if necessary.

Just call this function

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

examples

factorial(3)
factorial(11)

Just another way to do it, although it really isn't necessary.

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

You will probably find a Ruby feature request useful. It contains a nontrivial patch that includes a demo Bash script. The speed difference between a naive loop and the solution presented in the batch can be literally 100x (hundred fold). Written all in pure Ruby.

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

And yet another way (=

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)

Here is my version seems to be clear to me even though it's not as clean.

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

This was my irb testing line that showed each step.

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

Just one more way to do it:

# fact(n) => Computes the Factorial of "n" = n!

def fact(n) (1..n).inject(1) {|r,i| r*i }end

fact(6) => 720

Why would the standard library require a factorial method, when there is a built-in iterator for this exact purpose? It is called upto.

No you do not need to use recursion, like all these other answers show.

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

Rather, the built-in iterator upto can be used to calculate factorials:

factorial = 1
1.upto(10) {|x| factorial *= x }
factorial
 => 3628800

With high respect to all who participated and spent their time to help us, I would like to share my benchmarks of the solutions listed here. Params:

iterations = 1000

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)

For n = 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)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!