Перейти к содержанию

Реализации алгоритмов/Факториал

Материал из Викиучебника — открытых книг для открытого мира

Рекурсивные методы

[править]

Примеры реализаций рекурсивных функций для вычисления факториала.

  function fact(n : integer) : longint;
  begin
    if n <= 1 then fact := 1 else fact := n * fact(n - 1);
  end;

С подключённым модулем System.Math

  function fact(n : integer) : int64;
  begin
    Result:=IfThen(n <= 1, 1, n * fact(n - 1));
  end;
  int factorial(int n) {
   return n<=1 ? 1 : n * factorial(n-1);
  }
  int factorial(int n) {
    if(n<=1) return 1;
      return n*factorial(n-1);
  }

Common Lisp

[править]
 (defun factorial (n)
   (if (= n 0)
       1
       (* (factorial (- n 1)) n)))
 (defn fact[x]
   (if (<= x 1) 1 (* x  (fact (- x 1))  )))
  : factorial ( n -- n! )
    dup 0= if
      drop 1
    else
      dup 1- recurse *
    endif ;
  func Factorial(n uint) uint {
    if n == 0 {
        return 1
    }
    return n * Factorial(n - 1)
  }
(define (factorial n)
   (if (= n 0)
       1
       (* (factorial (- n 1)) n)))
def factorial n
  n > 1 ? n * factorial(n - 1) : 1
end
fn factorial_recursive (n: u64) -> u64 {
	match n {
		0 => 1,
		_ => n * factorial_recursive(n-1)
	}
}
 
fn main () {
	println!("{}", factorial_recursive(5))
}
function factorial($n)
{
  return $n ? $n * factorial($n-1) : 1;
}
#!/usr/bin/perl
sub factorial {
    my $n = shift;
    if ($n==0) {
        return 1;
    } else {
        return $n*factorial($n-1);
    }
}
print factorial(shift);

или однострочник

perl -e 'sub f{ $_[0] <= 1 ? 1 : $_[0] * f($_[0] - 1)}; print f(shift)' number
integer procedure factorial (n); integer n;
  factorial := if n=0 then 1 else n*factorial(n-1);
begin
  integer n;
  n:=10
  outint(n,5);
  outtext("! = ");
  outint(factorial(n),10);
  outimage;
end

Smalltalk

[править]
factorial
    "Answer the factorial of the receiver."
    self = 0 ifTrue: [^ 1].
    self > 0 ifTrue: [^ self * (self - 1) factorial].
    self error: Not valid for negative integers
func factorial(_ n: Int) -> Int {
    return n == 0 ? 1 : n * factorial(n-1)
}

Algol 68

[править]
PROC factorial = (INT n) INT:
BEGIN
   IF n=0 THEN
      1
   ELSE
      n*factorial(n-1)
   FI
END;
print (factorial(10))
function Factorial (N: Natural) return Natural is
begin
   if N = 0 then
      return 1;
   else
      return N * Factorial(N - 1);
   end if;
end Factorial;

или используя «if expression» (Ada 2012)

function Factorial (N: Natural) return Natural is
begin
   return (if N = 0 then 1 else N * Factorial(N - 1));
end Factorial;
\documentclass{article}
\usepackage{ifthen}
\newcounter{multi} \newcounter{multa}
\newcommand{\mult}[2]{ \setcounter{multi}{1} \setcounter{multa}{#1}
 \whiledo{\themulti < #2}{ \addtocounter{multa}{#1} \stepcounter{multi} } }
\newcounter{faki} \newcounter{faka}
\newcommand{\fac}[1]{
 \setcounter{faka}{1} \setcounter{faki}{2}
 \whiledo{\thefaki < #1}{
     \mult{\thefaka}{\thefaki}
     \setcounter{faka}{\themulta}
     \stepcounter{faki}}
 \mult{\thefaka}{\thefaki} \themulta}
\begin{document}
 \Huge $10!=\fac{10}$
\end{document}

Java и C#

[править]

Рекурсивный метод:

public int fact(int num) {
     return ((num > 1) ? num * fact(num - 1) : 1);
}

Если вы переживаете, что стек может быть переполнен, то используйте не рекурсивный метод:

public static uint Factorial(uint num)
{
     uint fact = 1;
     while (num > 1) fact *= num--;
     return fact;
}

JavaScript

[править]
var factorial = function factorialis (m) {
    var n = parseInt(m);
    return (n < 0 || m != n) ? NaN : (n == 0 ? 1 : n * factorialis(n - 1));
}

CoffeeScript

[править]
factorial = (n) -> !n and 1 or n * factorial(n - 1);
def factorial(x):
    return x * factorial(x - 1) if x > 1 else 1

или

factorial = lambda x: x and factorial(x - 1) * x or 1

или

import math
math.factorial(x)

или

from functools import reduce
factorial = reduce(lambda x, y: x * y, range(1, n + 1)
Factorial {
    0 = 1;
    s.Value = <Mul s.Value <Factorial <Sub s.Value 1>>>;
}
factorial :: Integer -> Integer
factorial 0 = 1
factorial n | n > 0 = n * factorial (n - 1)
factorial _ = error "Факториал не определен для отрицательных чисел"

или

factorial :: Integer -> Integer
factorial n = product [1..n]
long Factorial(int n)
{
    if (n <= 1)
        return 1;
    return n * Factorial(n - 1);
}

Нерекурсивные методы

[править]

Примеры реализаций нерекурсивных функций для вычисления факториала.

  function factorial(n : integer) : longint;
  var
    i : integer;
    f : longint;
  begin
      f := 1;
      for i := 2 to n do
        f := f * i;
      factorial := f
  end;
#!/usr/bin/perl
  sub factorial { 
      my $f=1; 
      my @fct= $f .. $_[0]; 
      foreach (@fct) {$f*=$_;} $f; 
      }
  int factorial(int n) {
      int result = 1;

      for ( int i = 2; i <= n; i++ ) {
          result *= i;
      }
      return result;
  }

Java и C#

[править]
public static int factorial(int num) {
	int fact = 1;
	for (; num > 1; fact *= num--);
        return fact;
}

JavaScript

[править]
const factorial = (n) => {
    if (n < 0) return NaN;
    let result = 1;
    for (let i = 1; i <= n; i++) {
	    result *= i;
    }
    return result;
}

CoffeeScript

[править]
factorial = (n) ->
  res = 1
  res *= n-- while n > 1
  res

или

factorial = (n) -> [1..n].reduce (x,y) -> x * y || 1
 (defun factorial (n)
    (if (< n 1)
      1
      (do ((f 1) (i 2 (1+ i)))
        ((> i n) f)
        (setq f (* f i)))))
integer function fact (n)
integer n
fact = 1
do i = 1,n
    fact = fact * i
enddo
return
end
program factorial
integer fact
external fact
n = 10
write (*,*) n,"! = ",fact(n)
end program factorial

Unix Shell

[править]
#!/bin/sh
result=1
for (( factor=$1 ; $factor ; factor=$factor-1 ))
do
     let -i result=$result*$factor
done
echo $result

CMD Shell

[править]
@echo off

set /p n=" n : "

set f=1 & for /l %%i in (1,1,%n%) do set /a f=%%i*f 

echo %f%

pause&exit
function factorial($n)
{
  $result = 1;

  for ($i=2; $i<=$n; $i++)
    $result *= $i;

  return $result;
}

или

function factorial($n) {
  return ($n <= 1) ? 1 : array_product(range(1,$n));
}
identification division.
program-id. factorial.
environment division.
data division.
working-storage section.
77 result pic 9(8).
77 n pic 9(8).
77 i pic 9(8).
procedure division.
main-line.
        display "Enter a positive number: " with no advancing
        accept n
        move 1 to result.
        perform varying i from 1 by 1 until i>n
                 multiply result by i giving result
        end-perform
        display "Factorial(" n ")= " result
        stop run.
input "N = "; n
f=1
for i = 1 to n
    f=f*i
next i
print n;"! = ";f

Программируемые калькуляторы «Электроника»

[править]

Примечание: команда ВП по адресу 00. превращает 0 в 1, позволяя корректно вычислять 0! = 1.

Вариант № 1

[править]

С использованием счётчика в адресуемом регистре (в качестве r следует выбрать один из регистров: 0, 1, 2, 3).

00. ВП     01. Пr     02. 1      03. ИПr    04. ×      05. FLr    06. 03     07. С/П

Вариант № 2

[править]

С использованием регистров стека X, Y, Z (значение, находившееся в регистре Y, сохраняется).

00. ВП     01. В↑     02. КНОП   03. 1      04. −      05. Fx≠0   06. 11     07. ×      08. FВx    09. БП
10. 03     11. F⟳     12. С/П

Вариант № 3

[править]

С использованием регистров стека X, Y, Z, T (т. е. стек используется целиком).

00. ВП     01. ↔      02. FВx    03. В↑     04. FВx    05. 1      06. -      07. ×      08. Fx=0   09. 03
10. ↔      11. С/П

AT&T x86 Assembler

[править]
factorial.s:      .globl factorial
                  factorial:
                          movl      $1, %eax
                          jmp      .L2
                  .L3:
                          imull     2(%esp), %eax
                          decl      78(%esp)
                  .L2:
                          cmpl      $1, 4(%esp)
                          jg       .L3
                          ret
factorial-main.c: #include <stdio.h>
                  extern int factorial (int n);
                  int main () {
                      int n = 10;
                      printf ("%d! = %d\n", n, factorial (n));
                  }

gcc factorial-main.c factorial.s
$func Factorial s.n = s.fact;
Factorial s.n =
    1 s.n $iter <Mult s.fact s.n> <Sub s.n 1> :: s.fact s.n,
    s.n : 0 =
    s.fact;
def factorial n
  (1..n).inject(:*) || 1
end

Без итераторов:

def factorial n
  f = 1
  for i in 2..n
    f *= i
  end
  f
end
def factorial(x):
    return reduce(lambda x, y : x * y, xrange(1, x + 1), 1)

С while циклом:

def factorial(x):
    res = 1
    while x > 0:
        res *= x
        x -= 1
    return res

С циклом for:

def factorial(a):
    if a == 0 or a == 1:
        return 1
    else:
        result = 1
        for i in range(2, a + 1):
            result *= i
        return result
factorial=: */@(>:@i.)

RSL (Object RSL)

[править]
Macro factorial (n)
   if (n < 0)
      fact = "Enter a positive number";
   elif (n == 0)
      fact = 1;
   else
      fact = i = 1;
      while (i <= n)
         fact = fact*i;
         i = i + 1;
      end;
   end;
   return fact;
end;
function Factorial (N: Natural) return Natural is
   Acc : Natural := 1;
begin
   for I in 2 .. N loop
      Acc := Acc * I;
   end loop;
   return Acc;
end Factorial;

См. также

[править]