]]> ]]>

Факториал

Вычисление факториала чисел от 0 до 16. Факториал n! = 1 * 2 * … * n.

Вывод программы должен выглядеть следующим образом:
0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
11! = 39916800
12! = 479001600
13! = 6227020800
14! = 87178291200
15! = 1307674368000
16! = 20922789888000

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

  • через рекурсивное определение факториала n! = n * (n-1)!
  • перемножением чисел от 1 до n в цикле.
  • использованием встроенной функции языка.

Пример для версий Lua 5.0, Lua 5.1

Используется рекурсивное определение факториала.

function factorial(n)
    if (n == 0) then
        return 1
    else
        return n * factorial(n - 1)
    end
end

for n = 0, 16 do
    io.write(n, "! = ", factorial(n), "\n")
end

Пример для версий Free Pascal 1.0.6, Free Pascal 2.0.4, Free Pascal 2.2.0, Free Pascal 2.2.4, gpc 20070904, PascalABC.NET 1.8, Turbo Pascal 4.0, Turbo Pascal 5.0, Turbo Pascal 5.5, Turbo Pascal 6.0, Turbo Pascal 7.0

Используется рекурсивное определение факториала.

Этот пример работает во всех перечисленных компиляторах, но с несколько разным результатом. В Turbo Pascal, Free Pascal и PascalABC.NET возникает арифметическое переполнение при вычислении факториалов 13-16, но Free Pascal сообщает об ошибке:

13! = Runtime error 215 at $004013C7
$004013C7
$00401449
$004063E0

в то время как Turbo Pascal и PascalABC.NET не обнаруживают ошибку и просто выводят неправильные значения:

13! = 1932053504
14! = 1278945280
15! = 2004310016
16! = 2004189184

Следует отметить, что в версиях Turbo Pascal 3.0 и младше этот пример не работает вообще из-за отсутствия типа данных longint.

В GNU Pascal пример работает без переполнения.

program factorial;

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

var
    n: integer;

begin
    for n := 0 to 16 do
        writeln(n, '! = ', fact(n));
end.

Пример для версий GHC 6.10.4, GHC 6.6.1

Используется рекурсивное определение факториала. Пример состоит из трех частей:

  • определение функции factorial, принимающей на вход один аргумент типа Integer (целое число неограниченной точности) и имеющей выход того же типа. Функция определяется рекурсивно, тип параметров задан в явном виде, чтобы избежать неоднозначности их определения.
  • определение функции line, которая выводит на печать число и его факториал в нужном формате. Использование команды printf аналогично языку C++.
  • собственно вывод чисел и их факториалов. Для этого командой [0..16] создается список чисел от 0 до 16, включительно. Функция двух аргументов map применяет первый аргумент (функцию line) к каждому элементу второго аргумента (списка [0..16]) и в результате создает список так называемых действий вывода (являющихся в Haskell обычными значениями). Для того, чтобы объединить эти действия в одно, используется команда sequence_, которая, будучи применена к списку действий, выполняет первое действие из списка и затем рекурсивно применяет себя к хвосту списка.
module Main where

import Text.Printf

factorial :: Integer -> Integer
factorial 0 = 1
factorial n = n * factorial (n - 1)

line x = printf "%d! = %d\n" x $ factorial x

main = sequence_ $ map line [0..16]

Пример для версий Bash 3.0, Bash 3.2.39, Bash 4.0.35, Bash 4.1.5

Используется рекурсивное определение факториала.

function factorial {
    typeset -i n=$1
    if [ $n = 0 ]; then
        echo 1
        return
    fi
    echo $(( n * $(factorial $(( n - 1 )) ) ))
}

for i in {0..16}
do
    echo "$i! = $(factorial $i)"
done

Пример для версий GCC 3, gcc 3.4.5, gcc 3.4.5 (Objective-C), GCC 4, TCC 0.9.25

Используется рекурсивное определение факториала.

#include <stdio.h>

unsigned long long factorial(unsigned long long n)
{
    if (n == 0) {
        return 1;
    } else {
        return n * factorial(n - 1);
    }
}

int main(void)
{
    int n;
    for (n = 0; n <= 16; n++) {
        printf("%i! = %lld\n", n, factorial(n));
    }

    return 0;
}

Пример для версий Borland C++ Builder 6, g++ 4.x

Используется рекурсивное определение факториала.

#include <iostream>

unsigned long long factorial(unsigned long long n)
{
	if (n == 0) 
		return 1;
	else 
		return n * factorial (n - 1);
}

int main(void)
{
    for (int n = 0; n <= 16; n++) 
        std::cout << n << "! = " << factorial(n) << std::endl;
    return 0;
}

Пример для версий MinGW

Используется рекурсивное определение факториала.

#include <stdio.h>

unsigned long long factorial(unsigned long long n)
{
    if (n == 0) {
        return 1;
    } else {
        return n * factorial (n - 1);
    }
}

int main(void)
{
    int n;
    for (n = 0; n <= 16; n++) {
        printf("%i! = %I64u\n", n, factorial(n));
    }

    return 0;
}

Пример для версий .NET 1.0, .NET 2.0, gmcs 2.0.1, Mono 1.2.4

Используется рекурсивное определение факториала.

using System;

class Program
{
    static long Factorial(int n)
    {
        if (n == 0)
            return 1;
        else
            return n * Factorial(n - 1);
    }
    static void Main(string[] args)
    {
        for (int i = 0; i < 17; i++)
            Console.WriteLine("{0}! = {1}",i,Factorial(i));
    }
}

Пример для версий GNU bc 1.06

Используется рекурсивное определение факториала.

#! /usr/bin/env bc
define factorial(n) {
    if (n == 0) return(1);
    return(n * factorial(n - 1));
}

for (n = 0; n <= 16; n++) {
    print n; "! = "; factorial(n);
}
quit

Пример для версий ARIBAS 1.53

Используется рекурсивное определение факториала функцией fac, т.к. имя factorial зарезервировано для встроенной функции вычисления факториала. В ARIBAS по умолчанию используется тип данных integer.

group(0) при выводе служит для отмены использования знака подчеркивания для разделения групп цифр.

function fac(n);
begin
    if (n = 0) then
        return(1);
    end;
    return(n * factorial(n - 1));
end;

function fac0_16();
var n;
begin
    for n := 0 to 16 do
        writeln(n, "! = ", fac(n): group(0));
    end;
end;

fac0_16().

Пример для версий ARIBAS 1.53

Используется встроенная функция factorial. В ARIBAS по умолчанию используется тип данных integer.

group(0) при выводе служит для отмены использования знака подчеркивания для разделения групп цифр.

function fac0_16();
var n;
begin
    for n := 0 to 16 do
        writeln(n, "! = ", factorial(n): group(0));
    end;
end;

fac0_16().

Пример для версий Nesla 0.6.0, Nesla 0.8.0

Для факториала 13-16 из-за арифметического переполнения возвращается nan (not a number). В результате вывод программы имеет следующий вид:

0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
11! = 39916800
12! = 479001600
13! = nan
14! = nan
15! = nan
16! = nan

#!/usr/bin/nesla
function factorial(n)
{
    if (n == 0) {
        return 1;
    } else {
        return n * factorial(n - 1);
    }
}

for (n = 0; n <= 16; n++) {
    print(n, "! = ", factorial(n), "\n");
}

Пример для версий Seed7 2007-06-07, Seed7 2007-06-24, Seed7 2012-01-01

Используется рекурсивное определение факториала. Для хранения значений факториала используется тип bigInteger, поэтому переполнения не происходит.

$ include "seed7_05.s7i";
  include "bigint.s7i";

const func bigInteger: factorial (in var bigInteger: n) is func
result
    var bigInteger: result is 1_;
begin
    if n = 0_ then
        result := 1_;
    else
        result := n * factorial(n - 1_);
    end if;
end func;

const proc: main is func
local
    var integer: n is 0;
begin
    for n range 0 to 16 do
        write(n); 
        write("! = ");
        write(factorial(bigInteger conv n)); 
        writeln;
    end for;
end func;

Пример для версий Seed7 2007-06-07, Seed7 2007-06-24, Seed7 2012-01-01

Используется встроенная функция !n, определенная только для типа данных integer. 13! больше максимально возможного значения этого типа, и попытка его вычисления вызывает арифметическое переполнение. В результате вывод программы имеет следующий вид:

0! = 1  
1! = 1  
2! = 2  
...
11! = 39916800  
12! = 479001600  
13! =  
*** Uncaught EXCEPTION NUMERIC_ERROR raised with
{! integer <80ba990>: <SYMBOLOBJECT> 0 }

{! (in integer <80ba990> param) } at factorial-builtin.sd7(10)
main no POSINFO
$ include "seed7_05.s7i";

const proc: main is func
local
    var integer: n is 0;
begin
    for n range 0 to 16 do
        writeln(n <& "! = " <& !n);
    end for;
end func;

Пример для версий Ruby 1.8.5, Ruby 1.9.0, Ruby 1.9.2

Используется рекурсивное определение факториала.

#! /usr/bin/env ruby
def factorial(n)
    if n == 0
        1
    else
        n * factorial(n - 1)
    end
end

0.upto(16) do |n|
    print(n, "! = ", factorial(n), "\n")
end

Пример для версий boo 0.7.6.2237, boo 0.8.2

Используется рекурсивное определение факториала. Из-за того, что функция factorial вызывается рекурсивно, для нее необходимо объявление типа возвращаемого значения.

def factorial(n as long) as long:
    if n == 0:
        return 1
    else:    
        return n * factorial(n - 1)

for n in range(0, 17):
	print("${n}! = ${factorial(n)}")

Пример для версий GHC 6.6.1

Функция fac определена как произведение чисел от 1 до n через встроенную функцию языка product.

module Main where

import Text.Printf

fac n = product [1..n]

main = sequence_ $ map (\x -> printf "%d! = %d\n" x $ fac x) [0..16]

Пример для версий Scala 2.5.1-final, Scala 2.7.7-final

Используется рекурсивное определение факториала.

object Factorial {
    def factorial(n: Int): Long = 
        if (n == 0) 1 
               else n * factorial(n - 1)
    def main(args: Array[String]) {
        for {i <- List.range(0, 17)} 
            yield { println(i + "! = " + factorial(i)) }
    }
}

Пример для версий fsharp 2.0.0

Используется сопоставление по образцу с последующим рекурсивным вызовом. Ключевое слово let задаёт новое определение — в данном случае функции factorial и printFact. rec означает, что определение будет рекурсивным. Сопоставление по образцу определяется ключевым словом match. factorial вычисляет сам факториал, а printFact выводит результаты вычислений в нужном формате.

let rec factorial n =
    match n with
    | 0 -> 1
    | _ -> n * factorial (n - 1)

let rec printFact n  =
    match n with 
    | 0 -> printfn "0! = 1"
    | _ -> printFact (n-1)
           printfn "%d! = %d"  n (factorial (n))
           
printFact(16)

Пример для версий Toka 1.2

Для факториалов 13-16 из-за арифметического переполнения возвращается неверное значение. Также не получилось убрать пробел между аргументом и знаком “!”. В результате вывод программы имеет следующий вид:

0 ! = 0
1 ! = 1
2 ! = 2
3 ! = 6
4 ! = 24
5 ! = 120
6 ! = 720
7 ! = 5040
8 ! = 40320
9 ! = 362880
10 ! = 3628800
11 ! = 39916800
12 ! = 479001600
13 ! = 1932053504
14 ! = 1278945280
15 ! = 2004310016
16 ! = 2004189184

#! /usr/bin/toka

[ dup 1 > [ dup 1 - recurse * ] ifTrue ] is factorial

0 17 [ i . i ." ! = " i factorial . cr ] countedLoop

bye

Пример для версий BlackBox Component Builder 1.5

Используется рекурсивное определение факториала.

О том как запустить программу на выполнение — см. Как запустить Блэкбокс и выполнить первую программу.

MODULE Example;

IMPORT StdLog;

PROCEDURE factorial(n: INTEGER): LONGINT;
BEGIN
  IF n = 0 THEN
    RETURN 1;
  ELSE 
    RETURN n * factorial(n-1)
  END;
END factorial;

PROCEDURE Do*;
VAR 
  n: INTEGER;
BEGIN
  FOR n := 0 TO 16 DO
    StdLog.Int(n);
    StdLog.String('! = '); 
    StdLog.Int(factorial(n));
    StdLog.Ln; 
  END;
END Do;    

END Example.

Пример для версий gpcp 1.3.4-JVM, gpcp 1.3.4-NET 1.1, gpcp 1.3.9-NET

Используется рекурсивное определение факториала.

MODULE Example;

IMPORT CPmain, Console, RTS;

VAR 
  n: INTEGER;
  s: ARRAY 15 OF CHAR;

PROCEDURE factorial*(n: INTEGER): LONGINT;
BEGIN
  IF n = 0 THEN
    RETURN 1;
  ELSE 
    RETURN n * factorial(n - 1)
  END;
END factorial;

BEGIN
  FOR n := 0 TO 16 DO
    Console.WriteInt(n, 2);
    Console.WriteString('! = ');
    RTS.LongToStr(factorial(n), s);  
    Console.WriteString(s);
    Console.WriteLn;
  END;
END Example.

Пример для версий Euphoria 3.1.1

Используется рекурсивное определение факториала.

function factorial(integer n)
    if n = 0 then
        return 1
    else
        return n*factorial(n-1)
    end if
end function

for n = 0 to 16 do
    printf(1,"%d! = %d\n",{n,factorial(n)})
end for

Пример для версий Oracle 10g SQL, Oracle 11g SQL

SQL не поддерживает циклы, рекурсии или пользовательские функции. Данный пример демонстрирует возможный обходной путь, использующий:

  • псевдостолбец level для создания псевдотаблиц t1 и t2, содержащих числа от 1 до 16,
  • агрегатную функцию sum, позволяющую суммировать элементы множества без явного использования цикла,
  • и математические функции ln и exp, позволяющие заменить произведение (необходимое для вычисления факториала) на сумму (предоставляемую SQL).

Строка “0! = 1” не войдет в набор строк, полученный в результате, т.к. попытка вычислить ln(0) приводит к исключению.

select t2.n || '! = ' || round(exp(sum(ln(t1.n))))
  from 
  ( select level n
      from dual
   connect by level <= 16) t1,
  ( select level n
      from dual
   connect by level <= 16) t2
 where t1.n<=t2.n
 group by t2.n
 order by t2.n

Пример для версий PHP 5.2.4, PHP 5.3.2

<?php

function factorial($n)
{
    if ($n == 0) {
        return 1;
    } else {
        return $n * factorial($n - 1);
    }
}

for ($n = 0; $n <= 16; $n++) {
    echo($n . "! = " . factorial($n) . "\n");
}

?>

Пример для версий clisp 2.47, Corman Common Lisp 3.0, gcl 2.6.6, SBCL 1.0.1, SBCL 1.0.29

Этот пример использует рекурсивное определение факториала, естественное для Lisp. Демонстрирует следующие особенности языка:

  • математические операторы: (- n 1) — это префиксная запись, эквивалентная инфиксной записи n-1;
  • операторы сравнения: (= n 0) возвращает T, если n равно нулю, и nil (используется как false) в противном случае;
  • условный оператор if: выражения в Lisp определяются по скобкам и могут записыватся в несколько строк;
  • определение функции с использованием defun;
  • макрос Common Lisp loop;
  • спецификации формата вывода в format: ~D соответствует целому числу, а ~% — концу строки.
(defun factorial (n)
    (if (= n 0)
        1
        (* n (factorial (- n 1))) ) )

(loop for i from 0 to 16
    do (format t "~D! = ~D~%" i (factorial i)) )

Пример для версий Borland C++ Builder 6, g++ 3.4.5, Microsoft Visual C++ 6, Microsoft Visual C++ 9 (2008)

Используется рекурсивное определение факториала. Реализация отличается от альтернативной использованием типа __int64 вместо unsigned long long и функции вывода на печать printf вместо std::cout <<.

#include "stdio.h"

__int64 factorial(__int64 n)
{
	return (n==0 ? 1 : n*factorial(n-1));
}

int main(int argc, char* argv[])
{
	for (int n=0; n<=16; n++)
		printf("%d! = %I64d\n",n,factorial(n));
	return 0;
}

Пример для версий gcj 3.4.5, Groovy 1.7, Sun Java 6

Используется рекурсивное определение факториала. Для хранения больших чисел использован элементарный тип данных long, позволяющий хранить числа от -263 до 263-1.

public class Factorial {
    static long factorial(int n)
    {
        return ( n==0 ? 1 : n*factorial(n-1) );
    }
    public static void main(String[] args)
    {
        for (int n=0; n<=16; n++)
            System.out.println(n+"! = "+factorial(n));
    }
}

Пример для версий gcj 3.4.5, Groovy 1.7, Sun Java 6

Используется итеративное вычисление факториала. Для хранения больших чисел используется встроенный класс BigInteger, позволяющий обрабатывать сколь угодно большие числа ценой увеличения времени обработки.

import java.math.BigInteger;

public class Factorial {
    public static void main(String[] args)
    {
        BigInteger f = new BigInteger("1");
        System.out.println("0! = " + f.toString());
        for (int n=1; n<=16; n++)
        {   f = f.multiply(new BigInteger(""+n));
            System.out.println( n + "! = " + f.toString());
        }
    }
}

Пример для версий Microsoft Visual Basic 6

Используется рекурсивное определение факториала. Из-за арифметического переполнения при вычислении факториалов 13-16 вывод программы заканчивается на строке “12! = …”, после чего в отдельном не-консольном окне выдается сообщение “Run-time error ‘6’: Overflow”.

Option Explicit

    Declare Function AllocConsole Lib "kernel32" () As Long
    Declare Function FreeConsole Lib "kernel32" () As Long
    Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
    Declare Function GetStdHandle Lib "kernel32" (ByVal nStdHandle As Long) As Long
    Declare Function WriteConsole Lib "kernel32" Alias "WriteConsoleA" _
           (ByVal hConsoleOutput As Long, lpBuffer As Any, ByVal _
           nNumberOfCharsToWrite As Long, lpNumberOfCharsWritten As Long, _
           lpReserved As Any) As Long
    Declare Function Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) As Long

Public Function Factorial(ByVal n As Integer) As Long
    If (n = 0) Then
        Factorial = 1
    Else
        Factorial = n * Factorial(n - 1)
    End If
End Function

Private Sub Main()
    'create a console instance
    AllocConsole
    'get handle of console output
    Dim hOut As Long
    hOut = GetStdHandle(-11&)
    'output string to console output
    Dim s As String
    Dim i As Integer
    For i = 0 To 16 Step 1
        s = i & "! = " & Factorial(i) & vbCrLf
        WriteConsole hOut, ByVal s, Len(s), vbNull, vbNull
    Next i
    'make a pause to look at the output
    Sleep 2000
    'close the handle and destroy the console
    CloseHandle hOut
    FreeConsole
End Sub

Пример для версий Microsoft Visual Basic 6

Используется итеративное определение факториала.

Option Explicit

    Declare Function AllocConsole Lib "kernel32" () As Long
    Declare Function FreeConsole Lib "kernel32" () As Long
    Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
    Declare Function GetStdHandle Lib "kernel32" (ByVal nStdHandle As Long) As Long
    Declare Function WriteConsole Lib "kernel32" Alias "WriteConsoleA" _
           (ByVal hConsoleOutput As Long, lpBuffer As Any, ByVal _
           nNumberOfCharsToWrite As Long, lpNumberOfCharsWritten As Long, _
           lpReserved As Any) As Long
    Declare Function Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) As Long

Private Sub Main()
    'create a console instance
    AllocConsole
    'get handle of console output
    Dim hOut As Long
    hOut = GetStdHandle(-11&)
    'output string to console output
    Dim s As String
    Dim i As Integer
    Dim f As Long
    f = 1
    s = "0! = 1" & vbCrLf
    WriteConsole hOut, ByVal s, Len(s), vbNull, vbNull
    For i = 1 To 16 Step 1
        f = f * i
        s = i & "! = " & f & vbCrLf
        WriteConsole hOut, ByVal s, Len(s), vbNull, vbNull
    Next i
    'make a pause to look at the output
    Sleep 2000
    'close the handle and destroy the console
    CloseHandle hOut
    FreeConsole
End Sub

Пример для версий QBasic 1.1, QuickBasic 4.50

Используется итеративное определение факториала. При вычислении 13! возникает арифметическое переполнение, и здесь поведение разных реализаций отличается: QBasic сообщает о переполнении, а QuickBasic просто выводит отрицательные значения. Кроме того, команда PRINT по умолчанию выводит по одному пробелу перед числом и после него.

DIM f AS LONG
f = 1
PRINT " 0 ! ="; f
FOR i = 1 TO 16:
    f = f * i:
    PRINT i; "! ="; f
NEXT i
END

Пример для версий QBasic 1.1, QuickBasic 4.50

По умолчанию для вычислений используется вещественный тип данных. Вывод программы имеет следующий вид:
0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
11! = 3.99168Е+07
12! = 4.790016Е+08
13! = 6.227021Е+09
14! = 8.717829Е+10
15! = 1.307674Е+12
16! = 2.092279Е+13

DECLARE FUNCTION factorial (n)

FOR i = 0 TO 16:
    PRINT STR$(i) + "! =" + STR$(factorial(i))
NEXT i
END

FUNCTION factorial (n)
    IF n = 0 THEN
        factorial = 1
    ELSE
        factorial = n * factorial(n - 1)
    END IF
END FUNCTION

Пример для версий EsCo 0.511 (Brainfuck), Müller's Brainfuck 2.0, weave.rb

В примере используется итеративное определение факториала: последний вычисленный факториал хранится в ячейке-переменной c6 и на каждом шагу умножается на очередное число, хранящееся в c5. Низкоуровневое описание приведено в комментариях к коду, запись “cXvY” означает, что после выволнения команд в строке указатель данных находится в ячейке X, и значение в этой ячейке равно Y.

Классический интерпретатор Brainfuck использует переменные типа byte для хранения значений в ячейках памяти, и уже 6! вызовет ошибку переполнения. Написание длинной арифметики на Brainfuck — задача достаточно трудоемкая, поэтому в примере предполагается, что в ячейках памяти могут храниться числа типа integer.

+++++++++++++++++++++++++++++++++			c1v33 : ASCII code of !
>++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++				c2v61 : ASCII code of =
>++++++++++						c3v10 : ASCII code of EOL
>+++++++						c4v7  : quantity of numbers to be calculated
>							c5v0  : current number (one digit)
>+							c6v1  : current value of factorial (up to three digits)
<<							c4    : loop counter
[							block : loop to print one line and calculate next
>++++++++++++++++++++++++++++++++++++++++++++++++.	c5    : print current number
------------------------------------------------	c5    : back from ASCII to number
<<<<.-.>.<.+						c1    : print !_=_

>>>>>							block : print c6 (preserve it)
>							c7v0  : service zero
>++++++++++						c8v10 : divizor
<<							c6    : back to dividend
[->+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]			c6v0  : divmod algo borrowed from esolangs; results in 0 n d_n%d n%d n/d
>[<+>-]							c6    : move dividend back to c6 and clear c7
>[-]							c8v0  : clear c8

>>							block : c10 can have two digits; divide it by ten again
>++++++++++						c11v10: divizor
<							c10   : back to dividend
[->-[>+>>]>[+[-<+>]>+>>]<<<<<]				c10v0 : another divmod algo borrowed from esolangs; results in 0 d_n%d n%d n/d
>[-]							c11v0 : clear c11
>>[++++++++++++++++++++++++++++++++++++++++++++++++.[-]]c13v0 : print nonzero n/d (first digit) and clear c13
<[++++++++++++++++++++++++++++++++++++++++++++++++.[-]] c12v0 : print nonzero n%d (second digit) and clear c12
<<<++++++++++++++++++++++++++++++++++++++++++++++++.[-]	c9v0  : print any n%d (last digit) and clear c9

<<<<<<.							c3    : EOL
>>+							c5    : increment current number
							block : multiply c6 by c5 (don't preserve c6)
>[>>+<<-]						c6v0  : move c6 to c8
>>							c8v0  : repeat c8 times
[
<<<[>+>+<<-]						c5v0  : move c5 to c6 and c7
>>[<<+>>-]						c7v0  : move c7 back to c5
>-
]
<<<<-							c4    : decrement loop counter
]

Пример для версий Microsoft SQL Server 2005, Microsoft SQL Server 2008 R2, Microsoft SQL Server 2012

Используется рекурсивное определение факториала, реализованное через рекурсивный запрос. Каждая строка запроса содержит два числовых поля — n и n!, и каждая следующая строка вычисляется с использованием данных из предыдущей.

Можно вычислить целочисленные факториалы только до 20!. При попытке вычислить 21! возникает ошибка “Arithmetic overflow error”, т.е. происходит переполнение разрядной сетки.

Для вещественных чисел вычисляется факториал 100! (Для этого в примере необходимо заменить bigint на float в 3-ей строке)

with factorial(n, f) as
(
 select 0, convert(bigint,1) 
  union all
 select n+1, f*(n+1) from factorial where n<20
)
select cast(n as varchar)+'! = '+cast(f as varchar)
  from factorial

Пример для версий iconc 9.4

Сокращенный вариант итеративного способа вычисления факториала.

procedure main ()
   local i, j
   every write (i := 0 to 16, "! = ", { j := 1; every j *:= 1 to i; j })
end

Пример для версий iconc 9.4

В примере используется рекурсивное определение факториала. 0 to 16 — генератор, возвращающий все числа в интервале от 0 до 16. every позволяет получить от генератора все числа и для каждого из них выполнить действие write.

procedure factorial (n)
   if n = 0 then
      return 1
   else if n > 0 then
      return n * factorial (n - 1)
end

procedure main ()
   local i
   every i := 0 to 16 do
      write (i, "! = ", factorial (i))
end

Пример для версий Interactive FP

Этот пример определяет четыре функции — две по необходимости, и две для читабельности. Все они принимают на вход скалярные значения; seq возвращает последовательность скаляров, остальные три — скаляры.

  • zero проверяет, равен ли ее аргумент нулю;
  • dec уменьшает аргумент на единицу;
  • seq возвращает <0>, если ее аргумент x равен нулю, и результат применения seq к (x-1) с присоединенным справа x иначе (если мы развернем это рекурсивное определение, мы получим просто последовательность <0 1 … x>) .
  • factorial возвращает 1, если ее аргумент x равен нулю, и результат применения factorial к (x-1), умноженный на x, иначе.

Последняя строка примера применяет factorial к каждому элементу последовательности, полученной применением seq к входному параметру — 16. Следует отметить, что все матеметические операции возвращают числа с плавающей запятой, поэтому результат выполнения программы будет иметь следующий вид: < 1 1.0 2.0 6.0 24.0 120.0 720.0 5040.0 40320.0 362880.0 3628800.0 3.99168E7 4.790016E8 6.2270208E9 8.7178289E10 1.30767428E12 2.09227885E13 >

{ zero ( = @ [id, %0] ) }
{ dec ( - @ [id, %1] ) }
{ seq ( zero -> %<0> ; apndr @ [ seq @ dec , id ] ) }
{ factorial ( zero -> %1 ; * @ [id, factorial @ dec ] ) }
&factorial @ seq:16

Пример для версий Visual Prolog 7.2

Для запуска создайте новый проект с UI Strategy “Console” и замените содержимое файлов main.cl и main.pro приведенным кодом.

В main.cl добавлена одна строка factorial : (integer N, integer F) procedure (i,o)., которая определяет бинарный предикат factorial с известным первым и неизвестным вторым аргументами. Ключевое слово procedure описывает поведение предиката, указывая, что его вычисление всегда будет успешным и будет найдено ровно одно решение, так что откаты не понадобятся.

В main.pro находится собственно определение нового предиката. Для каждого его вызова есть два возможных соответствия — с нулевым или произвольным первым аргументом. Visual Prolog перебирает формулы в порядке их появления в коде, так что если первый аргумент равен нулю, проверка начинается с первой формулы factorial(0,F). Первое правило формулы — !, так называемое отсечение, использование которого предотвращает откат ко второй формуле и таким образом обеспечивает наличие ровно одного решения предиката. После этого переменная F, содержащая решение предиката, устанавливается в 1 и выводится на печать. Вторая формула factorial(N,F) рекурсивно вычисляет F1 как факториал N-1, устанавливает решение предиката равным N*F1 и выводит его на печать. Наконец, stdio::nl печатает новую строку.

При выполнении основной программы предикат factorial выполняется ровно один раз, для N=12. С каждым вызовом рекурсии N уменьшается на единицу, пока не становится равным нулю. После этого значения факториалов возвращаются и выводятся на печать в порядке возрастания. Программа обрабатывает только факториалы до 12!, т.к. попытка вычисления 13! вызывает ошибку переполнения целочисленного типа.

% main.cl
class main
    open core

predicates
    classInfo : core::classInfo.
    factorial : (integer N, integer F) procedure (i,o).
predicates
    run : core::runnable.

end class main

% main.pro
implement main
    open core

constants
    className = "main".
    classVersion = "".

clauses
    classInfo(className, classVersion).
    factorial(0,F) :- 
        !,
        F = 1, 
        stdio::write("0! = 1"),
        stdio::nl.
    factorial(N,F) :-
        factorial(N-1,F1),
        F = N*F1,
        stdio::write(N, "! = ", F),
        stdio::nl.
        
clauses
    run():-
        console::init(),
        factorial(12,F),
        programControl::sleep(1000),
        succeed().
end implement main

goal
    mainExe::run(main::run).

Пример для версий Oracle 10g SQL, Oracle 11g SQL

Этот пример демонстрирует использование оператора model, доступного начиная с версии Oracle 10g и позволяющего обработку строк запроса как элементов массива. Каждая строка содержит два поля — номер строки n и его факториал f.

select n || '! = ' || f factorial
  from dual
 model
    return all rows
    dimension by ( 0 d ) 
    measures ( 0 f, 1 n )
    rules iterate (17)
    ( f[iteration_number] = decode(iteration_number, 0, 1, f[iteration_number-1]*iteration_number),
      n[iteration_number] = iteration_number
    );

Пример для версий MySQL 5

Замените TABLE на любую таблицу, к которой есть доступ, например, mysql.help_topic.

select concat(cast(t2.n as char), "! = ",  cast(exp(sum(log(t1.n))) as char))
  from 
  ( select @i := @i+1 AS n
      from TABLE, (select @i := 0) as sel1
      limit 16 ) t1,
  ( select @j := @j+1 AS n
      from TABLE, (select @j := 0) as sel1
      limit 16 ) t2
 where t1.n <= t2.n
 group by t2.n

Пример для версий VB.NET 9 (2008), vbnc 2.4.2

Используется рекурсивное определение факториала.

Module Module1
    Function Factorial(ByVal n As Integer) As Long
        If n = 0 Then
            Return 1
        Else
            Return n * Factorial(n - 1)
        End If
    End Function

    Sub Main()
        For i As Integer = 0 To 16
            Console.WriteLine(i & "! = " & Factorial(i))
        Next
    End Sub
End Module

Пример для версий Oracle 10g SQL, Oracle 11g SQL

Этот пример демонстрирует итеративное вычисление факториала средствами PL/SQL.

declare
    n    number := 0;
    f    number := 1;
begin
    while (n<=16)
    loop
        dbms_output.put_line(n || '! = ' || f);
        n := n+1;
        f := f*n;
    end loop;
end;

Пример для версий Free Pascal 2.0.4, Free Pascal 2.2.0, gpc 20070904, PascalABC.NET 1.8, Turbo Pascal 1.0, Turbo Pascal 2.0, Turbo Pascal 3.0, Turbo Pascal 4.0, Turbo Pascal 5.0, Turbo Pascal 5.5, Turbo Pascal 6.0, Turbo Pascal 7.0

Этот пример работает точно так же, как основной рекурсивный пример для Pascal, но использует тип real для хранения значений факториала. Команда writeln(f:-1:0) выводит дробное число f с 0 цифр после десятичной запятой и выравнивает его по левому краю.

program factorial;

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

var
    n: integer;

begin
    for n := 0 to 16 do
        writeln(n, '! = ', fact(n):-1:0);
end.

Пример для версий g95 0.93, gfortran 4.5.0, Intel Visual Fortran 11.1

Используется итеративное определение факториала и свободный формат программы. Спецификации формата I и A используются для вывода чисел в десятичном формате и строк, соответственно. При вычислении факториалов 13-16 возникает арифметическое переполнение, не вызывающее ошибку, поэтому выводятся неправильные значения:

13! = 1932053504
14! = 1278945280
15! = 2004310016
16! = 2004189184

program Factorial

  integer :: f,n
  f = 1
  n = 0
  do
    print "(I2, A, I10)", n, "! = ", f
    n = n + 1
    f = f * n
    if (n == 17) then
      exit
    end if
  end do

end program Factorial

Пример для версий Poplog 15.5 (Prolog)

Этот пример состоит из двух частей — первую часть кода следует сохранить в файле fact.pl, расположенном в рабочем каталоге Poplog, а вторую — ввести вручную в интерактивном режиме.

[-fact]. загружает базу фактов и правил из этого файла в текущую сессию Poplog (и выводит сообщение fact reconsulted, чтобы обозначить успешность загрузки). Запрос fact(16,X). пытается найти значение X, при котором этот предикат будет оценен как истинный. Вывод, требующийся в примере, будет побочным эффектом оценивания запроса, а основным результатом будет X = 20922789888000 ?. Это означает, что если вы недовольны такой привязкой переменных, вы можете отказаться от нее (введя ; ), и будет продолжен поиск лучшей привязки.

% fact.pl
fact(X, F) :- 
    ( X=0, F=1; 
      Y is X-1, fact(Y, Z), F is X*Z), 
    write(X), write('! = '), write(F), nl.

% interactive
[-fact].
fact(16,X).

Пример для версий Poplog 15.5 (POP-11)

Используется рекурсивное определение факториала. factorial(n) вычисляет значение n!, в то время как loop(n) используется в качестве цикла для перебора факториалов чисел от 0 до n, включительно. >< — оператор конкатенации. Следует отметить, что loop не возвращает значения.

Текст примера может быть набран в интерактивном режиме. Иначе можно сохранить определения функций в файл fact.p, находящийся в рабочем каталоге Poplog, и в интерактивном режиме ввести load fact.p для загрузки содержимого файла.

define factorial(n);
    if n == 0 
        then 1
        else n * factorial(n - 1)
    endif
enddefine;

define loop(n);
    if n>0 
        then loop(n-1)
    endif;
    n >< '! = ' >< factorial(n) =>
enddefine;

loop(16) =>

Пример для версий SpiderMonkey (Firefox 3.5)

Используется рекурсивное определение факториала. Пример предназначен для запуска из веб-браузера. Команда document.clear очищает текущую веб-страницу.

function factorial(n)
{   if (n == 0)
        return 1;
    else
        return n * factorial(n-1);
}
var i;
document.clear();
for (i = 0; i <= 16; i++)
    document.write(i + "! = " + factorial(i) + "<br />");

Пример для версий clisp 2.47, Corman Common Lisp 3.0, gcl 2.6.6, SBCL 1.0.1, SBCL 1.0.29

Внутренний цикл с операцией collect создает список чисел от 1 до n, после чего к нему применяется операция *.

(loop for n from 0 to 16
   do (format t "~D! = ~D~%" n 
        (apply '* (loop for i from 1 to n 
                        collect i)) ) )

Пример для версий Furry Paws

Этот пример работает точно так же, как пример для Interactive FP, за исключением отсутствия определения функции zero, являющейся встроенной. Следует отметить, что здесь все операции выполняются в пределах стандартного целочисленного типа, и 13! вызывает ошибку переполнения, поэтому программа может быть вызвана только для факториалов до 12!. show — альтернативный способ вывода информации.

dec = sub.[id, ~1]
seq = zero -> [id] ; cat.[seq.dec, [id]]
factorial = zero -> ~1 ; mul.[id, factorial.dec]

main = show.(return @factorial.(seq.~12))

Пример для версий gnat 3.4.5

В этом примере используется рекурсивное определение факториала.

Следует отметить, что для вывода на печать текста, целых и длинных целых чисел используются разные пакеты. Команда put в общем случае принимает несколько аргументов, изменяющих формат вывода: Item — это число, которое выводится на печать, Width — количество позиций, которые следует использовать при выводе, Fore и Aft — количества десятичных цифр, которые следует вывести до и после запятой и т.д. Если передается только один аргумент, он считается значением Item. Установив Width равным 1 или другому числу, меньшему, чем количество цифр в выводимом числе, можно вывести его без пробелов в начале (что является умолчательным способом для языка Ada).

Кроме того, отметим, что Ada не поддерживает неявные преобразования типов, так что для вычисления N*Fact(N-1) сначала следует явно преобразовать N к типу Long_Long_Integer.

with Ada.Text_IO, Ada.Integer_Text_IO, Ada.Long_Long_Integer_Text_IO;

procedure Factorial is
begin
   declare 
      function Fact (N: Integer) return Long_Long_Integer is
      begin
         if N=0 then
            return 1;
         else 
            return Long_Long_Integer(N)*Fact(N-1);
         end if;
      end Fact;
   i: Integer := 0;
   begin
      loop
         Ada.Integer_Text_IO.Put (Item => i, Width => 1);
         Ada.Text_IO.Put ("! = ");
         Ada.Long_Long_Integer_Text_IO.Put (Item => Fact(i), Width => 1);
         Ada.Text_IO.New_Line;
         i := i + 1;
         exit when i=17;
      end loop;
   end;
end Factorial;

Пример для версий UCBLogo 6.0

Используется рекурсивное определение факториала. В примере определяются две функции — factorial, вычисляющая N!, и print_factorial, которая выводит факториалы чисел от i до N.

to factorial :N
   ifelse :N = 0 [output 1] [output :N * factorial :N - 1]
end

to print_factorial :i :N
   repeat :N - :i + 1 [(print :i [! =] factorial :i)
                       make "i sum :i 1]
end

print_factorial 0 16

Пример для версий Scala 2.7.7-final

Используется итеративное определение факториала.

object Factorial {
    def main(args: Array[String]) {
        var f = BigInt(1)
        format("0! = %s\n", f)
        for {i <- 1 to 16} {
             f *= i;
             format("%s! = %s\n", i, f)
        }
    }
}

Пример для версий gawk 3.1.6, Jawk 1.02, mawk 1.3.3

Используется итеративное определение факториала. Отдельные команды в пределах блока могут разделятся точками с запятой или переносами строк.

BEGIN {
    f = 1
    print "0! = " f
    for (i=1; i<17; i++) {
        f *= i
        print i "! = " f
    }
}

Пример для версий S-lang 2.2.2

В примере используется рекурсивное определение факториала. Для создания рекурсивной функции в S-lang, следует сначала объявить ее (без списка параметров или реализации) и только потом собственно определить ее, указав параметры и тело функции.

В примере показано использование суффикса $. Строковая константа может оканчиваться суффиксом, который определяет то, как она обрабатывается. Суффикс $ означает, что перед использованием строки в ней будет произведена подстановка имен переменных: каждое имя переменной, предваренное префиксом $, будет заменено на значение переменной. При этом имя переменной должно быть отделено от следующих символов строки пробелом либо заключено в фигурные скобки.

Отметим, что типом данных по умолчанию является integer, поэтому в данном примере возникает ошибка переполнения при вычислении 13!.

define factorial ();

define factorial (n)
{   if (n==0) return 1;
     return n * factorial (n-1);
};

for (i=0; i<17; i++)
{   f = factorial (i);
    message ("${i}! = ${f}"$);
};

Пример для версий S-lang 2.2.2

Этот пример демонстрирует операции над массивами в S-lang. [1:i] создает список чисел от 1 до i; следует отметить, что для операций над массивами типом данных по умолчанию является double, даже если сами числа целые. Встроенная функция prod (с версии 2.1) вычисляет произведение элементов массива-аргумента. Встроенная функция sprintf предоставляет вывод в стиле языка C, шаблон %.0f печатает число с плавающей запятой с нулем цифр после запятой.

for (i=0; i<17; i++)
    sprintf ("%d! = %.0f", i, prod ( [1:i] ) );

Пример для версий Mathics 0.4, Wolfram Mathematica 7.0.1.0, Wolfram Mathematica 8.0.4

Используется встроенная функция вычисления факториала !. Do — один из способов реализации циклов; выполняет первый аргумент для всех значений, заданных вторым аргументом, а именно: для всех i от 0 до 16 с шагом 1.

Do[Print[i, "! = ", i!] , {i, 0, 16, 1}]

Пример для версий Euphoria 3.1.1

Используется итеративное определение факториала

integer f
f = 1
for n = 0 to 15 do
  printf(1,"%d! = %d\n",{n,f})
  f *= n+1
end for

Пример для версий Whitespacers (Ruby)

В этом примере используется другой метод комментирования — каждая команда предваряется ее словесным описанием. Числа и метки, кроме заключительного переноса строки, заключены в скобки.

Куча используется для хранения переменных: 1 — первое число, факториал которого не нужен, 2..5 — ASCII-коды символов, используемых при выводе на печать, 6 и 7 — текущее число и его факториал. Сам факториал вычисляется итеративно: на каждой итерации печатаются ранее вычисленное число и факториал, затем вычисляются и заносятся в память новые. После этого, новое число (ячейка 6) сравнивается с ячейкой 1: если число меньше, цикл повторяется, иначе прекращается.

Интересо, что в Whitespace ноль “отрицательный”: число должно содержать в записи хотя бы один Tab, в двоичной записи нуля единиц нет, поэтому приходится задавать знаковый бит и записывать ноль как Tab-LF.

push_1  { 	}
push_17  { 	   	}
store		 push_2  { 	 }
push_33  { 	    	}
store		 push_3  { 		}
push_32  { 	     }
store		 push_4  { 	  }
push_61  { 				 	}
store		 push_5  { 	 	}
push_10  { 	 	 }
store		 push_6  { 		 }
push_0  {	 }
store		 push_7  { 			}
push_1  { 	}
store		 label
  { }
printing_block_push_6  { 		 }
retrieve			print_as_number	
 	push_2  { 	 }
retrieve			print_as_char	
  push_3  { 		}
retrieve			print_as_char	
  push_4  { 	  }
retrieve			print_as_char	
  push_3  { 		}
retrieve			print_as_char	
  push_7  { 			}
retrieve			print_as_number	
 	push_5  { 	 	}
retrieve			print_as_char	
  increase_counter_block_push_6  { 		 }
push_6  { 		 }
retrieve			push_1  { 	}
add	   store		 calculate_next_factorial_block_push_7  { 			}
push_7  { 			}
retrieve			push_6  { 		 }
retrieve			multiply	  
store		 conditional_return_block_push_6  { 		 }
retrieve			push_1  { 	}
retrieve			subtract	  	jump_if_negative
		{ }
quit


end

Пример для версий erl 5.7.3

Используется рекурсивное определение факториала. В Erlang нет встроенных циклов, поэтому цикл приходится симулировать рекурсивной функцией, которая начинает с больших значений N, но делает рекурсивный вызов для N-1 до того, как выводит N!. loop(_) — ветвь, которая задает поведение функции, если ее аргумент — не целое число или отрицателен (необходима для корректного определения функции).

-module(prog).
 
-export([main/0, loop/1]).
 
fact(0) -> 1;
fact(N) -> N * fact(N-1). 
 
loop(N) when is_integer(N), N>=0 -> 
    loop(N-1),
    io:format("~B! = ~B~n",[N,fact(N)]);
loop(_) -> ok.
 
main() -> loop(16).

Пример для версий GDC 0.24

Используется рекурсивное определение факториала.

module factorial;

import std.stdio;

ulong recursive(ulong x)
{
	return (x == 0 ? 1 : x * recursive( x - 1 ));
}

int main()
{
	for (int i = 0; i < 17; ++i)
	{
		writefln("%s! = %s", i, recursive(i));
	}
	return 0;
}

Пример для версий GDC 0.24

Используется итеративное определение факториала. Отметим использование цикла foreach, в котором переменная цикла принимает все значения от нижней границы включительно до верхней исключительно.

module factorial;

import std.stdio;

int main()
{	ulong fact = 1;
	foreach (ulong i; 1..18)
	{	writefln("%s! = %s", i-1, fact);
		fact *= i;
	}
	return 0;
}

Пример для версий Perl 5.12.1

Используется функция reduce из модуля List::Util. Дополнительная единица в начале списка добавлена для того, чтобы пример работал даже тогда, когда список 1..$n пуст, т.е. при $n=0.

use List::Util qw(reduce);
sub fact {
  my $n = shift;
  reduce { $a * $b } 1, 1 .. $n
}
 
foreach my $i (0..16) {
    print "$i! = ", fact($i), "\n";
}

Пример для версий Perl 5.12.1

Используется рекурсивное определение факториала. Не совместим с Perl 6.

sub fact {
  my $n = shift;
  $n == 0 ? 1 : $n*fact($n-1);
}

foreach my $i (0..16) {
    print "$i! = ", fact($i), "\n";
}

Пример для версий Perl 5.12.1

Используется итеративное определение факториала. Не совместим с Perl 6.

sub fact {
  my $n = shift;
  my $result = 1;
  foreach my $i (1 .. $n) {
    $result *= $i;
  }
  $result
}

foreach my $i (0..16) {
    print "$i! = ", fact($i), "\n";
}

Пример для версий rakudo-2010.08

Используется метаоператор сокращения; [*] в начале списка означает “применить эту операцию к элементам списка”. Вывод результата можно также записать как

say "$i! = &fact($i)";
sub fact($n) { [*] 1..$n }

for 0..16 -> $i {
    say "$i! = ", fact($i);
}

Пример для версий Ruby 1.8.5, Ruby 1.9.0, Ruby 1.9.2

Факториал вычисляется как произведение набора чисел от 1 до n, дополненного еще одной 1 на случай 0!.

def fact(n)
  (1..n).inject(1) {|a,b| a*b}
end

(0..16).each {|x| puts "#{x}! = #{fact(x)}"}

Пример для версий Scratch 1.4

strs — массив строк переменной длины. Блок delete all необходим, чтобы очистить массив перед повторным запуском программы. repeat — цикл, повторяющий свое тело заданное количество раз. join — блок конкатенации аргументов. hide скрывает аватар спрайта (чтобы освободить больше места).

Scratch не поддерживает ни стандартный поток вывода, ни возможность “сказать” сообщение из нескольких строк, поэтому для вывода примера в нужной форме использовался массив.

delete all of strs
set i to 0
set f to 1
repeat 17
   add (join i (join (! = ) f)) to strs
   set i to (i + 1)
   set f to (f * i)
hide

Факториал на Scratch
Факториал на Scratch

Пример для версий Sanscript 2.2

Первый скриншот показывает главную диаграмму потоков. Ее основной частью является функция Repeat (аналог циклов в других языках), которая рассчитывает факториалы чисел и записывает их в список. У этой функции две пары входных и выходных контактов, которые соответствуют глобальным переменным в других языках, — factorial (хранит текущее значение факториала) и message (список строк текста (n)! = (n!)). Кроме того, есть еще один входной контакт N, который задает нужное количество итераций.

Входные контакты инициализируются константами и пустым списком, и цикл начинается. После конца вычислений message нужно вывести на печать. Это можно сделать при помощи функции Write List as Text, которая конкатенирует элементы списка в одну строку с заданным разделителем. Разделитель задается входным контактом sep; в данном случае это символ новой строки, сгенерированный функцией Char, которая преобразует ASCII-код в соответствующий символ. Наконец, полученная строка показывается функцией Display Message.

Второй скриншот демонстрирует внутренности функции Repeat. Элемент, обозначенный как “1, 2 …”, — счетчик цикла, начинающийся с 1 и увеличивающийся на 1 каждую итерацию. На каждой итерации factorial умножается на значение счетчика (функция Times). После этого новое значение конкатенируется со счетчиком и константой "! = " (функция Append Text). Наконец, полученная строка добавляется в список message (функция Add Last Item).

Факториал на Sanscript - главная диаграмма потоков
Факториал на Sanscript - главная диаграмма потоков

Факториал на Sanscript - блок Repeat
Факториал на Sanscript - блок Repeat

Пример для версий gc-2010-07-14

В примере показаны рекурсивный и итеративный способы вычисления факториала, а также создание обобщенной функции, которая выводит их результаты универсальным способом.

package main
import "fmt"

//Recursive Factorial
func factr(n uint64) uint64 {
    if (n < 2) { return 1 }
    return n * factr(n-1)
}

//Iterative Factorial
func facti(n uint64) uint64 {
    var ret uint64 = 1
    for ; n > 0; n-- {
        ret *= n
    }
    return ret
}

func printFact(fact func(uint64) uint64) {
    for i := 0; i < 17; i++ {
        fmt.Printf("%d! = %d\n", i, fact(uint64(i)))
    }
}

func main() {
    printFact(factr)
    fmt.Println("--")
    printFact(facti)
}

Пример для версий B-Prolog 7.4-3, gprolog 1.3.0, swipl 5.6.x

Как в GNU Prolog, так и в B-Prolog 12! не помещается в целочисленный тип данных, поэтому все значения после 11! неправильны. В SWI-Prolog переполнения не возникает.

| ?- [fact].

Результат для GNU Prolog: compiling /home/nickolas/Desktop/progopedia/prolog/fact.pl for byte code…
/home/nickolas/Desktop/progopedia/prolog/fact.pl compiled, 3 lines read — 1372 bytes written, 5 ms

Результат для B-Prolog: consulting::fact.pl

`| ?- fact(16,X).

0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
11! = 39916800
12! = -57869312
13! = -215430144
14! = 205203456
15! = -143173632
16! = -143294464

X = -143294464 ?`

% fact.pl
fact(X, F) :- 
    ( X=0, F=1; 
      Y is X-1, fact(Y, Z), F is X*Z), 
    write(X), write('! = '), write(F), nl.

% interactive
[fact].
fact(16,X).

Пример для версий gnuplot 4.2.2

Этот пример состоит из двух файлов — factorial.gp и run.gp, и эмулирует цикл с помощью команд load, reread и if. Используется встроенный оператор факториала. Этот оператор возвращает значение с плавающей точкой, поэтому для вывода используется функция gprintf, которая убирает нули после запятой и саму десятичную запятую.

### factorial.gp
print a, '! = ', gprintf("%.0f", a!)
a = a + 1
if (a <= 16) reread

### run.gp
#!/usr/bin/env gnuplot
a = 0
load "factorial.gp"

Пример для версий boo 0.8.2

В примере используется итеративное определение факториала. Переменная fact объявляется как принадлежащая к типу long в явном виде; иначе ее тип будет автоматически определен как int, и вычисление 13! вызовет ошибку переполнения.

fact as long = 1
for i in range(17):
    print("${i}! = ${fact}")
    fact = fact * (i+1)

Пример для версий gforth 0.7.0

Используется рекурсивное определение факториала. Forth — стек-ориентированный язык, поэтому все команды в нем основаны на работе со стеком. Так, DUP копирует верхний элемент стека, константа — добавляет число на верх стека, > — сравнивает второй сверху элемент с самым верхним, - — вычитает из второго сверху самый верхний и т.д.

: fac recursive
  dup 1 > IF
    dup 1 - fac *
  else
    drop 1
  endif ;
 
: lp
  swap 1 + swap
  do
    i . i ." ! = " i fac . cr
  loop ;
 
16 0 lp

Пример для версий C-INTERCAL 28.0, J-INTERCAL 0.11, J-INTERCAL 0.12

Используется итеративное определение факториала. Циклическая часть практически идентична примеру числами Фибоначчи, тело отличается, но незначительно. Отметим использование для переменных факториала и числа префикса : вместо . — первый означает 32-битные переменные, второй — 16-битные. Вывод выглядит следующим образом (числа идут парами, n и n!, и каждое число занимает две строки):

_                                                         


I

I

I

II

II

III

VI 

IV 

XXIV

V   

CXX 

VI  

DCCXX

VII  
_    
VXL  

VIII 
__     
XLCCCXX

IX     
_____          
CCCLXMMDCCCLXXX

X              
___________    
MMMDCXXVIIIDCCC

XI             
     _____     
xxxixCMXVIDCCC 

XII            

cdlxxixMDC     

XIII           
      ___      
mcmxxxMMLMMMDIV

XIV
          _____
mcclxxviiiCMXLVCCLXXX

XV
    ____
mmivCCCXXVI

XVI
    _______
mmivCLXXXIXCLXXXIV

C-INTERCAL использует для вывода римскую запись чисел, черта над знаком умножает его значение на 1000, а запись в нижнем регистре — на 1000000.

    DO .9 <- #17
    DO :10 <- #0
    DO :11 <- #1

    DO :2 <- :10

(1) PLEASE READ OUT :10
    PLEASE READ OUT :11

    DO :1 <- #1
    PLEASE (1509) NEXT
    DO :10 <- :3
    DO :2 <- :10
    DO :1 <- :11
    PLEASE (1549) NEXT
    DO :11 <- :3

    DO (3) NEXT
    DO (1) NEXT

(3) DO (4) NEXT
    PLEASE GIVE UP

(4) DO .1 <- .9
    DO .2 <- #1
    PLEASE (1010) NEXT
    DO .9 <- .3
    DO .1 <- '.9~.9'~#1
    PLEASE (1020) NEXT
    DO RESUME .1

Пример для версий Mozart 1.4.0

Используется итеративное определение факториала.

functor
 
import
   Application System

define 

local
   F
in
   F = {NewCell 1}
   for I in 0..16 do
       {System.showInfo {Append {Append {Int.toString I} "! = "} {Int.toString @F}}}
       F := (I+1) * @F
   end
   {Application.exit 0}
end

end

Пример для версий gst 3.1

В классе Number есть встроенный метод factorial, который здесь и используется.

0 to: 16 do: [ :i |
  i display.
  '! = ' display.
  i factorial displayNl
].

Пример для версий ActiveTcl 8.5, JTcl 2.1.0, Tcl 8.4, Tcl 8.5.7

Используется итеративный метод вычисления факториала. В Tcl 8.4 значения факториалов, начиная с 13!, вычисляются неправильно из-за переполнения. В более поздних версиях и других реализациях все значения правильны.

set fact 1
for {set i 0} {$i <= 16} {incr i} {
    puts "$i! = $fact"
    set fact [expr {$fact * ($i + 1)}]
}

Пример для версий Bash 3.0, Bash 4.0.35, Bash 4.1.5

Используется итеративное определение факториала.

f=1

for (( n=1; $n<=17; $((n++)) ));
do
  echo "$((n-1))! = $f"
  f=$((f*n))
done

Пример для версий Miller's Hack VM (JavaScript), Miller's Hack VM (Python)

Этот пример очень похож на вычисление чисел Фибоначчи, только в каждой итерации приходится выводить больше символов. Поскольку тип данных имеет размер 32 бита, 13! вызывает ошибку переполнения:

0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
11! = 39916800
12! = 479001600
!ERROR: integer overflow

28*0> 56*3+1> 84*2> 78*5+3> 25*4> 05> 16> 5<p1<P2<P3<P2<P6<p4<P 5<1+5> 5<6<*6> 0<1-0> 0<6? 67*c 

Пример для версий Roco 20071014

Используется итеративное определение факториала. В [0] хранится текущее число, [1] используется как временная переменная, в [2] хранится факториал текущего числа.

co calc{
/* break the loop when the counter is 17 - the number for which we don't need factorial */
eq [1] [0] 17
if [1] ac

/* output current factorial */
iout [0]
cout 33
cout 32
cout 61
cout 32
iout [2]
cout 13
cout 10

/* calculate next number and store it to [2]*/
add [0] [0] 1
mul [2] [2] [0]
}

/* initialize with 0! = 1 */
set [0] 0
set [2] 1

ca calc

ac

Пример для версий ncc 0.9.3

Используется рекурсивное определение факториала; хвостовая рекурсия оптимизируется до цикла при компиляции. За счет использования типа int по умолчанию при попытке вычислить 13! возникает ошибка переполнения:

Unhandled Exception: System.OverflowException: Number overflow.
def fact(i)
{
  | 0 => 1
  | other => other * fact(other - 1)
}
 
for (mutable i=0; i<16; i++)
    System.Console.WriteLine("{0}! = {1}", i, fact(i));

Пример для версий Factor 0.94

В первой строке перечисляются необходимые библиотеки: formatting (printf), kernel (dup), math (арифметические действия) и sequences (iota). Во второй строке объявляется имя текущего словаря — это необходимо для определения новых слов.

Затем определяется слово factorial, которое заменяет на стеке целое число n на его факториал. Для этого оно строит массив чисел от 0 до n — 1 с помощью слова iota и сворачивает его с единицей цитатой [ 1 + * ] (прибавление 1 и перемножение двух чисел) и комбинатором reduce.

Слово main генерирует массив чисел от 0 до 16 и комбинатором each применяет к ним цитату, которая вычисляет факториалы чисел и выводит их на печать.

В стандартном словаре math.combinatorics присутствует слово factorial, определенное указанным в примере образом.

USING: formatting kernel math sequences ;
IN: factorial-example

: factorial ( n -- n! )
    iota 1 [ 1 + * ] reduce ;

17 iota
[ dup factorial "%d! = %d\n" printf ] each

Пример для версий Web2c 2009

Данный пример использует итеративное определение факториала.

В макросе \factorial используются двойные фигурные скобки, т.к. в макросе присутствует цикл, который вызывается внутри другого цикла.

Рассчитываются только факториалы чисел до 12 включительно. Для больших чисел выполнение завершается с ошибкой “Arithmetic overflow”.

\newcount\n \newcount\p \newcount\m

\def\factorial#1{{\m=#1\advance\m by 1
\n=1
\p=1
\loop\ifnum\n<\m \multiply\p by \n \advance\n by 1 \repeat\number\p}}

\def\printfactorials#1{\m=#1\advance\m by 1
\n=0
\loop\ifnum\n<\m \hfil\break\number\n! = \factorial{\n} \advance\n by 1 \repeat}

\printfactorials{12}
\bye

Пример для версий Baltie 3

В этом примере используется итеративное определение факториала. Блок while получает в качестве аргумента условие продолжение выполнения цикла в круглых скобках, после чего следует тело цикла в фигурных скобках. Строковая переменная out содержит текст, который будет выведен в конце выполнения программы. Чтобы вывести переменную, состоящую из нескольких строк, спрайта следует переместить к верхнему краю экрана, чтобы вывод поместился на экран, а не вышел за его нижний край. 13! переполняется, но ошибки не происходит.

Факториал на Baltie 3
Факториал на Baltie 3

Факториал на Baltie 3 (результат)
Факториал на Baltie 3 (результат)

Пример для версий Io-2008-01-07

Используется итеративный метод вычисление факториала. Вывод программы для больших чисел выглядит следующим образом:

12! = 479001600
13! = 6.227021e+009
14! = 8.717829e+010
15! = 1.307674e+012
16! = 2.092279e+013
F := 1;
for(N,0,16,
   N print;
   "! = " print;
   F println;
   F := F * (N+1);
);

Пример для версий Objective Caml 3.10.2

Используется рекурсивное определение факториала. Значения факториалов, начиная с 13!, отрицательны из-за переполнения:

12! = 479001600
13! = -215430144
14! = -868538368
15! = -143173632
16! = -143294464
let rec factorial n =
    if n <= 1 then
      1
    else
      factorial (n-1) * n;;

let () =
  for n = 0 to 16 do
    Printf.printf "%d! = %d\n" n (factorial n)
  done;

Пример для версий Objective Caml 3.10.2

В этом примере используется вспомогательная функция fact, позволяющая реализовать хвостовую рекурсию.

let rec fact n accum =
    if n <= 1 then 
        accum
    else
        fact (n-1) (accum*n);;

let factorial n =
    fact n 1;;

let () =
    for n = 0 to 16 do
        Printf.printf "%d! = %d\n" n (factorial n)
    done;

Пример для версий MLton 20070826, Moscow ML 2.01, SML/NJ 110.69

В примере используется рекурсивное определение факториала. ^ — оператор конкатенации строк; преобразование чисел в строки выполняется в явном виде. ;; в конце программы — сигнал для интерактивной среды, что блок программы дописан и может быть интерпретирован. Во всех реализациях возникает ошибка переполнения при вычислении 13!, и программа прерывается.

Отметим, что Int (библиотека для работы с целыми числами) входит в базовую библиотеку Standard ML, но SML/NJ и MLton подгружают ее автоматически, а Moscow ML — нет. Чтобы эта программа заработала в Moscow ML, ее следует запускать с опцией -P full.

fun factorial n =
  if n <= 0 then 1
  else n * factorial (n-1)

val n = ref 0;
while !n <= 16 do (
  print (Int.toString (!n) ^ "! = " ^ Int.toString (factorial (!n)) ^ "\n");
  n := !n + 1
);;

Пример для версий Online Cat 1.3

В примере используется рекурсивный метод вычисления факториала. Принцип работы программы аналогичен вычислению чисел Фибоначчи.

define fact {
    dup 1 <= 
        [pop 1]
        [dup 1 - fact *]
    if
}

    0
    [dup write "! = " write dup fact writeln inc]
    [dup 16 lteq]
while

Пример для версий 64-bit BCPL Cintcode System (1 Nov 2006)

Используется рекурсивное определение факториала.

*n служит для печати символа перевода строки.

Вычисление факториала 15 и более вызывает арифметическое переполнение. В результате вывод программы имеет следующий вид:

0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
11! = 39916800
12! = 479001600
13! = 6227020800
14! = 87178291200
15! = 18000
16! = 000

GET "libhdr"

LET start() = VALOF
{ FOR i = 0 TO 16 DO writef("%n! = %n*n", i, factorial(i))
  RESULTIS 0
}

AND factorial(n) = n=0 -> 1, n*factorial(n-1)

Пример для версий OpenCOBOL 1.0, TinyCOBOL 0.65.9

Используется итеративное определение факториала.

Тип переменной, в которой хранится значение факториала — 9(15), т.е. число из 15 знаков. Числа, указанные перед именами переменных, — номера уровней; в более сложных программах они позволяют определять переменные как коллекции других переменных, но в данном случае это не используется. Уровень 77 — специальный; переменные этого уровня соответствуют обычным локальным переменным и не могут входить в сложные составные структуры.

Команда MULTIPLY, вопреки интуитивному предположению, умножает первый аргумент на второй и помещает результат во второй аргумент. Команда DISPLAY добавляет перевод строки после аргумента, поэтому элементы вывода приходится приводить к строчному типу (методом сохранения их в строковые переменные соответствующего размера) и конкатенировать. Для умножения добавлена обработка возможного переполнения, хотя это необязательно.

Вывод программы зависит от компилятора: числа всегда выводятся фиксированной ширины (дополненные нулями спереди), в TinyCOBOL — ширины 18, в OpenCOBOL — 15.

       IDENTIFICATION DIVISION.
       PROGRAM-ID. SAMPLE.

       DATA DIVISION.
       WORKING-STORAGE SECTION.

         77 fact pic 9(15) comp.
         77 n pic 99.
         77 i pic 99.
         77 ist pic XX.
         77 factst pic X(18).

       PROCEDURE DIVISION.
         move 16 to n
         move 0 to i
         move 1 to fact
         perform until i greater than n
           move i to ist
           move fact to factst
           display ist "! = " factst
           add 1 to i
           multiply i by fact
             on size error display "value too big"
           end-multiply
         end-perform.
         stop run.

Пример для версий Bash 3.0, Bash 3.2.39, Bash 4.0.35, Bash 4.1.5, mksh R40

Пример, работающий в версиях Unix shell, не поддерживающих синтаксис for i in {0..16} или ((i = 0; i <= 16; i++)): цикл for конструируется “вручную”.

В mksh используются 32-битовые целые числа, так что для факториалов чисел больше 13 в этой реализации происходит переполнение.

function factorial {
    typeset -i n=$1
    if [ $n = 0 ]; then
        echo 1
        return
    fi
    echo $(( n * $(factorial $(( n - 1 )) ) ))
}

i=0
while [[ $i -le 16 ]] 
do
    echo "$i! = $(factorial $i)"
    ((i++))
done

Пример для версий Groovy 1.7

Используется итеративное определение факториала: для вычисления факториала числа единица умножается последовательно на все числа от 1 до этого числа.

def fact = {n ->
   BigInteger factorial = 1
   (1..n).each { factorial *= it }
   return factorial
}

(0..16).each { println "${it}! = ${fact(it)}" }

Пример для версий Groovy 1.7

Используется рекурсивное определение факториала. Для того, чтобы функция могла рекурсивно обращаться сама к себе, она должна иметь отдельное объявление перед реализацией. Если тип значения, возвращаемого функцией, не задан, по умолчанию используется целочисленный, и при вычислении 13! возникает переполнение целого.

def fact
fact = { n ->
   (n == 0 ? 1 : n * fact(n-1) )
}

(0..16).each { println "${it}! = ${fact(it)}" }

Пример для версий Falcon 0.9.6.6

Используется итеративное определение факториала.

fact = 1
for i in [0:16]
    printl (i, "! = ", fact)
    fact *= (i+1)
end

Пример для версий Falcon 0.9.6.6

Используется рекурсивное определение факториала.

function fact(n)
    if n==0: return 1
    return n * fact(n-1)
end

for i in [0:16]
    printl (i, "! = ", fact(i))
end

Пример для версий Clojure 1.0.0, Clojure 1.1.0

Используется рекурсивное определение факториала. Функция range с одним аргументом генерирует список чисел от 0 включительно до этого числа исключительно. str — функция конкатенации строк. Функция dec эквивалентна (- x 1). doseq — цикл for в Clojure.

(defn factorial [x]
  (if (< x 2)
    1
    (* x (factorial (dec x)))))

(doseq [i (range 17)]
  (println (str (str i "! = ") (factorial i))))

Пример для версий Clojure 1.0.0, Clojure 1.1.0

Для вычисления факториала числа создается интервал чисел от 2 до этого числа, и вычисляется произведение этих чисел (функция apply).

(doseq [i (range 17)]
  (println (str (str i "! = ") (apply * (range 2 (inc i))))))

Пример для версий guile 1.8.5, JScheme 7.2, MIT/GNU Scheme 7.7.9

Используется рекурсивное определение факториала. Отметим, что GNU Guile и MIT/GNU Scheme выводит правильный результат, а в JScheme возникает переполнение, и факториалы с 13! вычисляются неправильно.

(define (factorial x)
  (if (< x 2)
    1
    (* x (factorial (- x 1)))))

(do ((i 0 (+ i 1)))
  ((> i 16))
    (display (string-append (number->string i) "! = "))
    (display (number->string (factorial i)))
    (newline))

Пример для версий Acme-Chef-1.01

Используется итеративное вычисление факториала. Ингредиенты, измеряющиеся в ml, — жидкие и соответствуют символам в выводе, измеряющиеся в g — сухие и соответствуют числам.

Программа состоит из двух циклов. Первый, chop ... until choped — вычисляет факториал следующего числа и заносит в первую миску все элементы (символы и числа), которые нужно будет вывести на печать. Но из-за того, что факториалы вычисляются по возрастанию, первыми нужно выводить значения со дна стека. Для этого используется вторая миска и второй цикл mash ... until mashed, который перекладывает элементы из первой миски во вторую, в результате чего они будут поступать на печать в правильном порядке.

В текущей версии интерпретатора неправильно обрабатываются жидкие ингредиенты — ни модификаторы при их объявлении, ни команда luquify не переводят их в жидкое состояние, поэтому вывод программы выглядит следующим образом:

0 33 32 61 32 1 10 1 33 32 61 32 1 10 2 33 32 61 32 2 10 3 33 32 61 32 6 10 4 33 32 61 32 24 10 5 33 32 61 32 120 10 6 33 32 61 32 720 10 7 33 32 61 32 5040 10 8 33 32 61 32 40320 10 9 33 32 61 32 362880 10 10 33 32 61 32 3628800 10 11 33 32 61 32 39916800 10 12 33 32 61 32 479001600 10 13 33 32 61 32 6227020800 10 14 33 32 61 32 87178291200 10 15 33 32 61 32 1307674368000 10 16 33 32 61 32 20922789888000 10

Factorial as a Piece of Cake.

This recipe calculates and prints factorials of first integers.

Ingredients.
33 ml exclamation
32 ml space
61 ml equal
10 ml newline
0 g n
1 g f
1 g one
17 g iterator
119 g second iterator

Method.
Liquify exclamation.
Liquify space.
Liquify equal.
Liquify newline.
Chop iterator.
Put n into 1st mixing bowl.
Put exclamation into 1st mixing bowl.
Put space into 1st mixing bowl.
Put equal into 1st mixing bowl.
Put space into 1st mixing bowl.
Put f into 1st mixing bowl.
Put newline into 1st mixing bowl.
Put n into 1st mixing bowl.
Add one into 1st mixing bowl.
Fold n into 1st mixing bowl.
Put f into 1st mixing bowl.
Combine n into 1st mixing bowl.
Fold f into 1st mixing bowl.
Chop iterator until choped.
Mash second iterator.
Fold n into 1st mixing bowl.
Put n into 2nd mixing bowl.
Mash second iterator until mashed.
Pour contents of 2nd mixing bowl into the baking dish.

Serves 1.

Пример для версий Pike 7.6, Pike 7.8

Используется рекурсивное определение факториала. Тип int может содержать произвольно большие числа.

int factorial(int n) {
    return ( n<=1 ? 1 : n * factorial(n-1) );
}

int main() {
    for (int n=0; n<=16; n++)
        write(n+"! = "+factorial(n)+"\n");
    return 0;
}

Пример для версий befungee 0.2.0

Программа состоит из двух циклов — первый вычисляет числа от 16 до 1, второй — собственно факториалы.

Прежде всего в стек заносится 16 (как 4*4) — максимальное число, факториал которого нужно вычислить. Затем следует первый цикл, выполняющийся по часовой стрелке. За одну итерацию в стек дописывается число, равное предыдущему, уменьшенному на 1. Когда это число становится нулем, цикл прерывается (_ во второй строке), и указатель инструкций направляется вправо.

Перед входом во второй цикл из стека удаляется верхний элемент (0) и добавляется 1 (текущее значение факториала). Затем следует второй цикл, выполняющийся против часовой стрелки. За одну итерацию происходит следующее:

  • \ — два верхних элемента (ранее вычисленный факториал и следующее число) стека меняются местами (число становится верхним элементом). Если в стеке всего один элемент, поверх него записывается 0.
  • :_ — если следующее число — 0 (или стек пуст), цикл прерывается.
  • . — следующее число выводится на печать (копия остается в стеке).
  • блок ,,,,"! = " — помещает в стек символы строки и сразу же их выводит. Строка проходится справа налево, но и символы выводятся от самого верхнего к нижним, так что для программиста строка выглядит так же, как на печати.
  • .:* — вычисляется новый факториал и выводится на печать (копия остается в стеке).
  • ,*25 — вывод перевода строки.
44* >:1-:v    v ,*25 .:* ,,,,"! = ".:_ @ 
    ^    _ $1 > \:                   ^ 

Пример для версий Morphett's FALSE, Wouter's FALSE 1.2.CF

Используется итеративное вычисление факториала. В переменных i и f хранятся текущее число (счетчик цикла) и текущее значение факториала. После инициализации переменных начинается цикл: [i;17=~] — условие продолжения цикла: пока i не равно 17. Затем следует тело цикла, в котором выводится значение i и символьная константа, затем i увеличивается на 1, выводится старое значение факториала и вычисляется новое.

Для Wouter’s FALSE 1.2.CF значения факториала 13 и больше вычисляются с ошибкой из-за переполнения.

0i: 1f: 
[i;17=~]
[i; $."! = " 1+$i: f;$.10, *f:]
#

Пример для версий Objeck 2.0.3

Используется встроенная функция Factorial.

bundle Default {
    class Factorial {
        function : Main(args : String[]) ~ Nil {
            for (i := 0; i <= 16; i += 1;) {
                i->Print();
                "! = "->Print();
                i->Factorial()->PrintLine();
            };
        }
    }
}

Пример для версий Lingua::Shakespeare 1.00

Используется итеративное определение факториала. В первой сцене инициализируются переменная факториала (счетчик цикла по умолчанию равен 0), а также ряд переменных-символов. Вторая сцена — цикл, в котором выводятся текущее число и его факториал, а затем проверяется, равно ли текущее число 17 — если да, цикл прекращается.

use Lingua::Shakespeare;

Elizabethan Factorial.

Ferdinand, for factorial.
Isabella, for loop index.
Emilia, for exclamation mark.
Sebastian, for space.
Egeus, for equality sign.
Lucio, for newline.

Act I: Factorial calculations.

Scene I: Initialization.

[Enter Isabella and Sebastian]

Isabella:
  You are as fat as the product of a big black furry old cat and a white cow!

[Exit Sebastian]
[Enter Emilia]

Isabella:
  You are as distasteful as the sum of Sebastian and a chihuahua!

[Exit Emilia]
[Enter Egeus]

Isabella:
  You are as good as the difference between the sum of Sebastian and Emilia and a bold brave hero!

[Exit Egeus]
[Enter Lucio]

Isabella:
  You are as cute as the sum of a peaceful warm delicious summer's day and a cute squirrel!

[Exit Lucio]
[Enter Ferdinand]

Isabella:
  You brother!

Scene II: Loop.

Ferdinand:
  Open your heart!

[Exit Ferdinand]
[Enter Emilia]

Isabella:
  Speak your mind!

[Exit Emilia]
[Enter Sebastian]

Isabella:
  Speak your mind!

[Exit Sebastian]
[Enter Egeus]

Isabella:
  Speak your mind!

[Exit Egeus]
[Enter Sebastian]

Isabella:
  Speak your mind!

[Exit Sebastian]
[Enter Ferdinand]

Isabella:
  Open your heart!

[Exit Ferdinand]
[Enter Lucio]

Isabella:
  Speak your mind!

[Exit Lucio]
[Enter Ferdinand]

Ferdinand:
  You are as good as the sum of yourself and a rose.

Isabella:
  You are as gentle as the product of myself and yourself.
  Am I not as beautiful as the sum of your sweet charming lovely noble sister and a flower?

Ferdinand:
  If so, let us return to scene II.

[Exeunt]

Пример для версий npiet 1.2

Этот пример сгенерирован автоматически. Ниже приведена исходная программа, из которой он был получен. Используется итеративное вычисление факториала. Значения 13! и больше вычисляются неправильно из-за переполнения.

main()
{
  f = 1;
  for ( i = 0; i <= 16; i++ )
  {
    __outn(i);
    asm{ @"! = " }
    __outn(f);
    __out(10);
    f = f * (i+1);
  }
}

Факториал на Piet
Факториал на Piet

Факториал на Piet (увеличение 4x)
Факториал на Piet (увеличение 4x)

Пример для версий Python 2.6.5

Используется итеративный способ вычисления факториала.

def factorial(n):
    if n == 0:
        return 1
    
    f = 1
    for i in range(1, n + 1):
        f *= i
    return f

for n in range(16 + 1):
    print "%d! = %d" % (n, factorial(n))

Пример для версий Python 2.6.5

Используется рекурсивное определение факториала.

def factorial(n):
    if n == 0:
        return 1
    else:
        return n * factorial(n - 1)

for n in range(16 + 1):
    print "%d! = %d" % (n, factorial(n))

Пример для версий GNU Octave 3.2.3

Используется встроенная функция factorial. Отметим, что на числах такого масштаба результат получается точный, но в общем случае Octave не предназначен для вычислений произвольной точности, и большие значения факториала будут вычисляться с ошибками.

for i = 0 : 16
  printf("%d! = %d\n", i, factorial(i));
endfor

Пример для версий GNU Octave 3.2.3

Используется рекурсивное вычисление факториала. Точка с запятой в конце строки подавляет автоматический вывод только что вычисленного значения (в данном случае fact) в интерактивном режиме, чтобы не засорять отформатированный вывод.

fact = 1;
for i = 0 : 16
  printf("%d! = %d\n", i, fact);
  fact *= i+1;
endfor

Пример для версий GNU Octave 3.2.3

Используется рекурсивное вычисление факториала.

function f = fact(n)
  if (n <= 1)
    f = 1;
  else
    f = n * fact(n - 1);
  endif
endfunction

for i = 0 : 16
  printf("%d! = %d\n", i, fact(i));
endfor

Пример для версий Borland Delphi 2.0

Этот пример практически полностью повторяет пример для Turbo Pascal, единственное изменение — добавление строк

{$APPTYPE CONSOLE}
uses SysUtils;

Для компиляции примера в среде Delphi 2 нужно выполнить следующие действия:

  • File -> New Application
  • Project -> Remove from Project -> удалить Unit1 (Form1)
  • View -> Project Source -> заменить весь текст файла проекта на текст примера
  • File -> Save Project As -> “factorial.dpr”
  • Project -> Compile

Скомпилированный файл factorial.exe нужно запустить из командного интерпретатора Windows.

При запуске непосредственно из среды Delphi нужно добавить строчку readln; перед последней строкой (end.): таким образом программа будет ожидать нажатия “ENTER” до закрытия консольного окна.

Как и в Turbo Pascal, из-за переполнения данный пример выводит неверные значения для факториала 13 и больше:

13! = 1932053504
14! = 1278945280
15! = 2004310016
16! = 2004189184

program factorial;
{$APPTYPE CONSOLE}
uses SysUtils;

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

var
    n: integer;

begin
    for n := 0 to 16 do
        writeln(n, '! = ', fact(n));
end.

Пример для версий APS APLAN

В первой строке объявляются имена процедур и систем переписывающих правил, которые будут определены в этой программе. Имя task объявлять не нужно, т.к. это имя самой программы (совпадает с именем файла).

Следующий блок — определение функции вычисления факториала как системы переписывающих правил; на это указывает ключевое слово rs в определении. Правила, применяющиеся к аргументу, перечислены в круглых скобках через запятую. В данном случае все правила простые, т.е. применяются к аргументам безусловно.

Затем следует процедура вывода факториалов на печать (ключевое слово proc). Ключевое слово loc задает список локальных переменных. После него в круглых скобках перечислены операторы процедуры через точку с запятой. Вместо конкатенации аргументов функции prn (вывод на печать) можно просто перечислить аргументы подряд.

При выполнении программы в онлайн-интерпретаторе вывод имеет заданный вид; при выполнении в интерпретаторе локально в выводе появляются лишние кавычки:

0 "! = " 1
1 "! = " 1

и т.д.

INCLUDE <include/std.ap>

NAMES factorial, print_factorials;

factorial := rs(x) (
    0 = 1,
    1 = 1,
    x = x * factorial(x - 1)
);

print_factorials := proc(n)loc(i)(
    i := 0;
    while(i < n,
        prn i"! = "factorial(i);
        i := i + 1
    )
);

task := print_factorials 17;

Пример для версий Regina 3.3

В примере используется рекурсивное определение факториала.

REXX позволяет установить произвольную точность вычислений. В данном случае 14 знаков необходимо для того, чтобы все факториалы выводились как целые числа. Без первой строки факториалы, начиная с 13!, выводятся как числа с плавающей точкой.

Конкатенация строк может выполняться оператором || или в неявном виде при последовательном перечислении величин и констант. Если величины разделены пробелами, эти пробелы добавляются и в итоговую строку.

Слово procedure в определении функции необязательно; оно указывает на то, что переменные подпрограммы локальны; в противном случае они будут глобальными в пределах программы.

  numeric digits 14

  do n = 0 to 16
    say n"! = "factorial(n)
  end
exit

factorial: procedure
  parse arg n .
  if n = 0 then
    n = 1
  else
    n = n * factorial(n - 1)
  return n

Пример для версий Rust 0.1

В этом примере используется рекурсивное вычисление факториала. Из-за переполнения типа uint значения 13! и больше выводятся с ошибкой.

use std;
import std::io;

fn factorial(x: int) -> uint {
  if (x <= 1) {
    ret 1u;
  } else {
    ret (x as uint) * factorial(x - 1);
  }
}

fn main() {
  let i = 0;
  while i <= 16 {
    io::println(#fmt("%d! = %u", i, factorial(i)));
    i = i + 1;
  }
}

Пример для версий Ceylon M1

В этом примере факториалы вычисляются итеративно. Ключевое слово variable указывает на то, что значение переменной fact будет изменяться позднее (в Java, напротив, ключевое слово final указывает на то, что значение переменной изменяться не будет). Тип Integer позволяет хранить значения факториалов без переполнения. Оператор конкатенации аргументов команды print не требует отдельного оператора, но при этом первый и последний элемент из списка конкатенируемых должны быть строками.

void run() {
    variable Integer fact := 1;
    for (i in 0..16) {
        print("" i "! = " fact "");
        fact *= i + 1;
    }
}

Пример для версий Cool 2008

class Main : IO is
  Main() begin
    out_string("Enter an integer greater-than or equal-to 0: ");

    let input: Integer := in_int(); in
      if input < 0 then
        out_string("ERROR: Number must be greater-than or equal-to 0\n")
      else
        out_string("The factorial of ").out_int(input);
        out_string(" is ").out_int(factorial(input))
      fi
    end
  end;

  factorial(num: Integer): Integer := if num = 0 then 1 else num * factorial(num - 1) fi;
end;

Пример для версий Factor 0.94

В этом примере используется чисто рекурсивное вычисление факториала. Слово factorial заменяет на стеке n на n! с побочным эффектом: выводом всех значений факториалов от 0 до n. После выполнения комбинатора if на стеке остаются значения n и n!, которые словами swap и over заменяются на n!, n, n!; два последних значения используются при выводе, первое остается на стеке в качестве возвращенного.

В основной части программы main приходится добавить drop значения 16!, чтобы сигнатура программы оставалась ( -- ).

USING: formatting kernel math ;
IN: factorial-example

: factorial ( n -- n! )
    dup
    0 =
    [ 1 ]
    [ dup dup 1 - factorial * ]
    if
    swap over "%d! = %d\n" printf ;

16 factorial
drop

Пример для версий Factor 0.94

В этом примере используется встроенное слово factorial, определенное в библиотеке math.combinatorics.

USING: formatting kernel math.combinatorics sequences ;

17 iota [ dup factorial "%d! = %d\n" printf ] each

Пример для версий loljs 1.1

Используется рекурсивное определение факториала.

HAI
  HOW DUZ I FACTORIAL N
    BOTH SAEM 0 AN N
    O RLY?
      YA RLY
        FOUND YR 1
      NO WAI
        FOUND YR PRODUKT OF N AN FACTORIAL DIFF OF N AN 1
    OIC
  IF U SAY SO
  
  I HAS A N ITZ 0
  IM IN YR LOOP UPPIN YR N WILE N SMALLR THAN 17
    VISIBLE SMOOSH N "! = " FACTORIAL N
  IM OUTTA YR LOOP
KTHXBYE

Пример для версий loljs 1.1

Используется итеративное определение факториала.

HAI
  I HAS A N ITZ 0
  I HAS A FACTORIAL ITZ 1
  IM IN YR LOOP UPPIN YR N WILE N SMALLR THAN 17
    VISIBLE SMOOSH N "! = " FACTORIAL
    FACTORIAL R PRODUKT OF FACTORIAL AN SUM OF N AN 1
  IM OUTTA YR LOOP
KTHXBYE

Пример для версий Dyalog APL 13.1

Первая строка задает значение индекса первого элемента в списках (в данном случае 0). Вторая строка задает точность при выводе чисел (она должна превышать длину максимального факториала).

Третья строка при чтении справа налево делает следующее:

  • ⍳17 генерирует список из 17 индексов, начинающихся с 0, т.е. 0 … 16.

  • 17 / ⊂'!=' генерирует список из 17 строк !=. — оператор enclose, который позволяет оперировать строками как скалярами, а не как массивами символов. / — оператор репликации.

  • !⍳17 применяет к каждому элементу списка унарную операцию ! — факториал.

  • , — бинарная операция конкатенации правого и левого аргументов; после двух конкатенаций выражение принимает значение 0 1 2 3 4 ... 15 16 != != ... != 1 1 2 6 24 120 720 5040 40320 362880 ..., т.е. список чисел, список строк и затем список факториалов.

  • 3 17⍴ изменяет форму списка-аргумента, получая из него матрицу из 3 строк и 17 столбцов:

    ┌→─┬──┬──┬──┬──┬───┬───┬────┬─────┬──────┬───────┬────────┬─────────┬──────────┬───────────┬─────────────┬──────────────┐  
    ↓0 │1 │2 │3 │4 │5  │6  │7   │8    │9     │10     │11      │12       │13        │14         │15           │16            │  
    ├~─┼~─┼~─┼~─┼~─┼~──┼~──┼~───┼~────┼~─────┼~──────┼~───────┼~────────┼~─────────┼~──────────┼~────────────┼~─────────────┤  
    │!=│!=│!=│!=│!=│!= │!= │!=  │!=   │!=    │!=     │!=      │!=       │!=        │!=         │!=           │!=            │  
    ├─→┼─→┼─→┼─→┼─→┼──→┼──→┼───→┼────→┼─────→┼──────→┼───────→┼────────→┼─────────→┼──────────→┼────────────→┼─────────────→┤  
    │1 │1 │2 │6 │24│120│720│5040│40320│362880│3628800│39916800│479001600│6227020800│87178291200│1307674368000│20922789888000│  
    └~─┴~─┴~─┴~─┴~─┴~──┴~──┴~───┴~────┴~─────┴~──────┴~───────┴~────────┴~─────────┴~──────────┴~────────────┴~─────────────┘
    
  • наконец, транспонирует эту матрицу так, что в каждой строке находятся три элемента — число, строка-разделитель и факториал числа.

В итоге вывод программы имеет следующий вид:

     ┌→─┬──┬──────────────┐          
     ↓0 │!=│1             │          
     ├~─┼─→┼~─────────────┤          
     │1 │!=│1             │          
     ├~─┼─→┼~─────────────┤          
     │2 │!=│2             │          
     ├~─┼─→┼~─────────────┤          
     [...25 lines of output ...]  
     ├~─┼─→┼~─────────────┤          
     │16│!=│20922789888000│          
     └~─┴─→┴~─────────────┘

Матрица оформлена как таблица с границами между ячейками из-за того, что она содержит boxed строки.

IO←0
⎕PP←18
⍉3 17⍴ (⍳17) , (17 /'!=') , !⍳17

Пример для версий Wolfram Mathematica 8.0.4

Используется рекурсивное определение факториала. Обратите внимание на то, что при определении функции ее аргумент дополняется символом _.

Fact[n_] := If[n == 0, 1, Fact[n - 1]*n];
For[i = 0, i <= 16, i++, Print[i, "! = ", Fact[i]]];

Пример для версий CPL

(Пример взят из описания языка) Здесь приведено рекурсивное определение факториала. Для реализации разных сценариев обработки для разных значений аргумента вместо условного перехода if используется условное выражение.

rec function Fact1[x] = (x = 0) → 1, xFact1[x — 1]

Пример для версий CPL

(Пример взят из описания языка) Здесь приведено итеративное определение факториала.

Выражение result of позволяет использовать блок или составную команду как выражение. Для этого тело блока должно содержать присвоение значения переменной result. В блоке можно определять локальные переменные и нельзя создавать побочные эффекты (например, изменять значения внешних переменных). Чаще всего это выражение используется при определении функций.

В теле цикла используется одновременное присвоение новых значений переменным. Поскольку обе переменные используют маленькие имена, язык позволяет пропустить знак умножения между ними — xf трактуется как x * f.

function Fact2[x] = result of
    § real f = 1
      until x = 0 do
          f, x := xf, x — 1
      result : = f §

Пример для версий PostgreSQL 9.1

В PostgreSQL задача вычисления факториала решается полностью встроенными средствами: постфиксной функцией ! (существует также префиксная форма !!) и функцией generate_series, которая генерирует набор строк, содержащих значения от первого до второго аргумента, включительно.

select n || '! = ' || (n!)
  from generate_series(0,16) as seq(n);

Пример для версий Baltie 3

Более лаконичная версия программы вычисления факториалов, предоставленная Bohumír Soukup из SGP Systems. Вычисленные значения выводятся в поток вывода напрямую, без промежуточной переменной.

Факториал на Baltie 3 (более лаконичная версия)
Факториал на Baltie 3 (более лаконичная версия)

Пример для версий Dyalog APL 13.1

В этом примере факториал числа N вычисляется как свертка списка чисел от 1 до N, включительно, при помощи выражения ×/1+⍳. Анонимная D-функция применяет это выражение к своему правому аргументу и конкатенирует его с самим аргументом и строкой-разделителем. Функция, в свою очередь, применяется к списку чисел от 0 до 16, записанному в столбик (т.е. как двухмерный массив 17x1). Вывод программы выглядит следующим образом:

 ┌→───────────────────┐      
 ↓0 != 1              │      
 ├+──────────────────→┤      
 │1 != 1              │      
 ├+──────────────────→┤      
 │2 != 2              │      
 ├+──────────────────→┤      
 [...25 lines of output ...]  
 ├+──────────────────→┤      
 │16 != 20922789888000│      
 └+──────────────────→┘
IO←0
⎕PP←18
{, '!=', ×/1+⍳⍵}¨17 1⍴⍳17

Пример для версий Nimrod 0.8.8

Используется рекурсивное вычисление факториала.

proc factorial(n: int): int64 =
  if n == 0:
    result = 1
  else:
    result = n * factorial(n - 1)

for i in countup(0,16):
  echo i, "! = ", factorial(i)

Пример для версий Nimrod 0.8.8

Факториал вычисляется итеративно. Отметим, что тип int64 в определении переменной факториала пропустить нельзя, иначе ее тип будет выведен как int, и переменная переполнится на 13!.

var f: int64 = 1
for i in countup(0,16):
  echo i, "! = ", f
  f = f * (i + 1)

Пример для версий VBA 6.3, VBA 6.5

Факториал вычисляется итеративно; значения накапливаются в строковой переменной и затем выводятся в одном окне. & — оператор конкатенации, CStr преобразует число в строку (несмотря на то, что факториал хранится как число с плавающей точкой, выводится он без дробной части), Chr возвращает символ с заданным ASCII-кодом.

Sub Factorial()
    Dim f As Double
    Dim res As String
    f = 1
    For i = 0 To 16
        res = res & CStr(i) & "! = " & CStr(f) & Chr(10)
        f = f * (i + 1)
    Next i
    MsgBox (res)
End Sub

Пример для версий VBScript 5.7, VBScript 5.8

Факториал вычисляется итеративно. Обратите внимание на то, что переполнения переменной-факториала не происходит, несмотря на то, что ее тип определяется автоматически.

f = 1
For i = 0 To 16
   WScript.Echo(i & "! = " & f)
   f = f * (i + 1)
Next

Пример для версий bwBASIC 2.50

Используется итеративная схема вычисления факториала. Реализация Bywater BASIC отличается тем, что тип переменной объявляется в явном виде только для массивов; в остальных случаях используется вывод типов. Переполнения при вычислении факториалов не возникает.

f = 1
FOR i = 0 TO 16
    PRINT i; "! ="; f
    f = f * (i + 1)
NEXT i

Пример для версий ECLiPSe CLP 6.0 #188

Используется рекурсивное определение факториала.

Для организации цикла в предикате main используется специфичная для ECLiPSe итеративная управляющая структура (мета-предикат) for.

factorial(0, 1) :- 
    !.
factorial(N, F) :-
    N > 0,
    N1 is N - 1,
    factorial(N1, F1),
    F is N * F1.

main :-
    ( for(N, 0, 16) do
        factorial(N, F),
        write(N), write('! = '), write(F), nl ).

Пример для версий Wirth's PL/0 (1976)

В языке нет возможности выводить символы, поэтому программа выводит пары число-его факториал, без разделителей. Результат запуска этой программы имеет следующий вид:

    0 var n, f;  
    1 begin  
    2    n := 0;  
    4    f := 1;  
    6    while n # 16 do  
   10    begin  
   10       n := n + 1;  
   14       f := f * n;  
   18    end;  
   19 end.  
    0  jmp  1    1  
    1  int  1    5  
    2  lit  1    0  
    3  sto  1    3  
    4  lit  1    1  
    5  sto  1    4  
    6  lod  1    3  
    7  lit  1   16  
    8  opr  1    9  
    9  jpc  1   19  
   10  lod  1    3  
   11  lit  1    1  
   12  opr  1    2  
   13  sto  1    3  
   14  lod  1    4  
   15  lod  1    3  
   16  opr  1    4  
   17  sto  1    4  
   18  jmp  1    6  
   19  opr  1    0  
 start pl/0
0
1
1
1
2
2
3
6
4
24
5
120
6
720
7
5040
8
40320
9
362880
10
3628800
11
39916800
12
479001600
13
1932053504
14
1278945280
15
2004310016
16
2004189184
 end pl/0
var n, f;
begin
   n := 0;
   f := 1;
   while n # 16 do
   begin
      n := n + 1;
      f := f * n;
   end;
end.

Пример для версий A++ Interpreter

Первое выражение загружает библиотеку init, содержащую основные конструкции языка (циклы, условные переходы, сравнения и т.д.). Все эти конструкции не входят в основу языка и определяются через примитивы; так, например, конструкция if определяется следующим образом:

(define true   (lambda (x y) 
               x))
(define false  (lambda (x y) 
               y))
(define if     (lambda (b t f) 
               (b t f)))

Второе выражение определяет факториал как рекурсивную функцию. Отметим, что стандарт языка определяет два вида чисел — обычные целые с привычными арифметическими действиями и “понятийные” zero, one, two, ..., ten. Числа разных видов не перекодируются друг в друга и используются отдельно; в данном случае применяются обычные целые.

Третье выражение определяет основной цикл, и четвертое — вызывает его. Команда print завершает вывод переводом строки, в результате вывод программы имеет следующий вид:

-->0
-->! = 
-->1
-->1
-->! = 
-->1
-->2
-->! = 
-->2
-->3
-->! = 
-->6
-->4
-->! = 
-->24
-->5
-->! = 
-->120
...

Значения факториалов вычисляются правильно до 12!, затем происходит переполнение, и последующие значения выводятся как -1.

(load "app/init.app")

(define factorial (lambda(n)
  (if (equal n 0)
    1
    (* n (factorial (- n 1))))))

(define main
  (lambda(n)
    (while (not (equal n 17))
      (lambda()
        (print n)
        (print "! = ")
        (print (factorial n))
        (define n (+ n 1))))))

(main 0)

Пример для версий f2c 20090411, g95 0.93, gfortran 4.5.0

Этот пример написан в фиксированном формате (стиль FORTRAN 77) и использует итеративное вычисление факториала.

Fortran позволяет пропускать объявления переменных; в таком случае он выводит их типы сам, но, в отличие от более поздних языков, не по контексту использования переменной, а по ее имени — если первая буква названия I..N, выбирается тип INTEGER, иначе — REAL. В данном случае обе переменные целые.

Цикл DO в данном случае соответствует циклу FOR более поздних языков: счетчик цикла N последовательно пробегает все значения от 0 до 16. Тело цикла заканчивается на строке с меткой 1, которая указана в заголовке цикла.

Команда PRINT использует формат вывода по умолчанию, который варьируется в зависимости от используемого компилятора.

      PROGRAM FACTOR
        NF = 1
        DO 1,N = 0,16
          PRINT *, N, "! =", NF
1         NF = NF * (N + 1)
      END

Пример для версий R 2.10.1

Используется итеративное вычисление факториала. Функция paste конкатенирует безымянные аргументы, именованный аргумент sep задает разделитель, использующийся при конкатенации (по умолчанию — пробел).

f <- 1
for (n in 0:16) {
  print(paste(n, "! = ", f, sep = ""))
  f <- f * (n + 1)
}

Пример для версий R 2.10.1

Используется встроенная функция prod, вычисляющая произведение всех элементов массива. Для n = 0 ответ был бы неправильным, т.к. массив 1:0 состоит из двух элементов — 1 и 0.

for (n in 1:16) {
  print(paste(n, "! = ", prod(1:n), sep = ""))
}

Пример для версий MIPS32

13! и дальше вызывают переполнение, поэтому вывод такой:

1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
11! = 39916800
12! = 479001600
13! = 1932053504
14! = 1278945280
15! = 2004310016

.data
  string1: .asciiz "! = " 
  string2: .asciiz "\n"

  
.text

main:

 li $t1, 1
 li $t2, 1

 j loop

loop:

  li $v0, 1
  la $a0, ($t2)
  syscall
  
  la $a0, string1
  li $v0, 4
  syscall 
  
  mult $t1,$t2
  mflo $t1
  
  li $v0, 1
  la $a0, ($t1)
  syscall
  
  la $a0, string2
  li $v0, 4
  syscall 
  
  addiu $t2,$t2,1
  
  beq $t2, 16, endloop
  j loop
  
  

endloop:
  
  li $v0, 10
  syscall   

Пример для версий Python 3.x

Используется функциональное определение факториала.

import functools

factorial = lambda n: functools.reduce(lambda a, b: a * b, range(1, n + 1), 1)

for n in range(16 + 1):
    print "%d! = %d" % (n, factorial(n))

Пример для версий bcplkit UNIX v7

Используется рекурсивное вычисление факториала. Числа больше 13! вызывают переполнение.

Вывод:

0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
11! = 39916800
12! = 479001600
13! = 1932053504
14! = 1278945280
15! = 2004310016
16! = 2004189184

GET "LIBHDR"

LET START() = VALOF 
$(1
	FOR I = 1 TO 16 DO
    	WRITEF("%N! = %I4*N", I, FACT(I))
    RESULTIS 0
$)1

AND FACT(N) = N = 0 -> 1, N * FACT(N - 1)

Пример для версий E-on-Java 0.9.3

E — язык с неявной типизацией; :int, указанный в сигнатуре функции, — не объявление типа, а ограничение (guard) — контракт на то, что функция factorial будет работать только с целочисленными аргументами и возвращать только целочисленные значения. Эти ограничения не обязательны, но полезны при проведении аудита безопасности кода.

def factorial(n :int) :int {
  if (n == 0) {
    return 1
  } else {
    return n * factorial(n-1)
  }
} 

for n in 0..16 {
  println(n.toString(10) + "! = " + factorial(n).toString(10))
}

Пример для версий Picat 0.1 (beta-1), Picat 0.7

Используется рекурсивное определение факториала, реализованное с помощью предиката.

factorial(0, F) => F = 1.
factorial(N, F), N > 0 => factorial(N - 1, F1), F = N * F1.

main =>
     foreach (I in 0 .. 16)
          factorial(I, F),
          writef("%w! = %w\n", I, F)
     end.

Пример для версий Picat 0.1 (beta-1), Picat 0.7

Используется рекурсивное определение факториала, реализованное с помощью функции.

factorial(0) = 1.
factorial(N) = F, N > 0 => F = N * factorial(N - 1).

main =>
     foreach (I in 0 .. 16)
          writef("%w! = %w\n", I, factorial(I))
     end.

Пример для версий GAP 4.4.12

Используется стандартная функция Factorial.

for n in [0..16] do
    Print(n, "! = ", Factorial(n), "\n");
od;

Пример для версий Dart 1.1.1

Используется рекурсивное определение факториала. Тип данных int позволяет хранить целые числа произвольной величины.

int factorial(int n) => n == 0 ? 1 : n * factorial(n - 1);

main() {
  for (int i = 0; i <= 16; ++i) {
    print('$i! = ${factorial(i)}');
  }
}

Пример для версий Dart 1.1.1

Используется итеративное вычисление факториала.

main() {
  int fact = 1;
  for (int i = 0; i <= 16; ++i, fact *= i) {
    print('$i! = $fact');
  }
}

Пример для версий Snap! 4.0

Для вывода результатов вычислений в нужной форме используется глобальная переменная — список, которая “показывается” в конце выполнения программы.

Факториал (итеративное вычисление) на Snap!
Факториал (итеративное вычисление) на Snap!

Пример для версий Snap! 4.0

В этом примере используется рекурсивный способ вычисления факториала. В Snap! существует возможность создания пользовательских блоков, в данном случае — блока factorial типа reporter (блок, возвращающий значение, т.е. функция). Созданный блок сразу появляется в палитре блоков, и его можно использовать при редактировании его определения, т.е. для рекурсивных вызовов.

Факториал (рекурсивное вычисление) на Snap!
Факториал (рекурсивное вычисление) на Snap!

Пример для версий Wolfram Mathematica 8.0.4

Символу f[x] ставится в соответствие список (List[…]) первых x натуральных чисел, генерируемый функцией Range[x], в которой головная часть List заменяется на Times при помощи функции Apply[head, expr], записанной здесь как head@@expr.

Здесь использованы две парадигмы программирования, реализованные в Wolfram: во-первых, с помощью шаблонного выражения x_ число, вписанное в квадратные скобки, подставляется в соответствующее место справа от знака отсроченного присваивания := . Во-вторых, функциональная парадигма позволила избавить код от громоздких процедурных конструкций и придти к похожей на математическую записи.

fact[x_]:=Times@@Range[x];

Пример для версий Rust 1.0.0-alpha.2

fn factorial(x: i64) -> i64 {
  if x <= 1 {
    1
  } else {
    x * factorial(x - 1)
  }
}

fn main() {
  for i in 0..17 {
    println!("{}! = {}", i, factorial(i));
  }
}

Пример для версий Windows PowerShell 5.0

function Get-Factorial ($n) {
    if ($n -eq 0) {
        return 1
    }
    $fact = 1
    1..$n | ForEach { $fact *= $_ }
    return $fact
}

foreach ($i in 0..16) {
    echo ("{0}! = {1}" -f $i,(Get-Factorial $i))
}

Пример для версий Clarion C10

используется рекурсия. вычисляются 20 членов ряда.

1! = 1 2! = 2 3! = 6 4! = 24 5! = 120 6! = 720 7! = 5040 8! = 40320 9! = 362880 10! = 3628800 11! = 39916800 12! = 479001600 13! = 6227020800 14! = 87178291200 15! = 1307674368000 16! = 20922789888000 17! = 355687428096000 18! = 6402373705728000 19! = 121645100408832000 20! = 2432902008176640000

  PROGRAM

OMIT('***')
 * User: Shur
 * Date: 29.02.2016
 * Time: 23:49
 ***

  MAP
      include('i64.inc')
Factorial PROCEDURE(SHORT,*INT64 a)
ShowINT64  PROCEDURE(*INT64 a),STRING
  END

a                    LIKE(INT64)
b                    LIKE(INT64)
c                    LIKE(INT64)
str1                 CSTRING(32000)
str2                 CSTRING(32000)

   CODE       
      Factorial(20,a)
      message(str1,'Factorial',,,,10b)

Factorial            PROCEDURE(SHORT n,*INT64 a)
b like(INT64)
   CODE
      if n = 1 then
         i64Assign(a,1)
         str1 = '1! = 1'
         RETURN
      .
      i64Assign(b,n)     
      Factorial(n-1,a)
      if a.lo = 0 and a.hi = 0
         RETURN
      .   
      i64Mult(a,b,c)
      if i64Sign(c) = -1 
         i64Assign(a,0)
         RETURN
      .   
      a :=: c
      str1 = str1 & '|' & n & '! = ' & ShowINT64(a)
      
ShowINT64           PROCEDURE(a)
d DECIMAL(30,0)
   CODE
      i64ToDecimal(d,a)
      return(d)

Пример для версий Microsoft SQL Server 2005

declare @max_n tinyint = 20
;with t as (
   select 1 as n, convert(bigint,1) as f
   union all
   select n+1, f*(n+1) from t
   where n < @max_n
   
)
select convert(varchar,n)+'! = '+convert(varchar(32),f)+', ' 
from t as [text] 
FOR XML PATH ('')

Работа программистам