Факториал
Вычисление факториала чисел от 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
Пример для версий 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 - блок 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 (результат)
Пример для версий 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 (увеличение 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 (более лаконичная версия)
Пример для версий 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! 4.0
В этом примере используется рекурсивный способ вычисления факториала. В Snap! существует возможность создания пользовательских блоков, в данном случае — блока factorial
типа reporter
(блок, возвращающий значение, т.е. функция). Созданный блок сразу появляется в палитре блоков, и его можно использовать при редактировании его определения, т.е. для рекурсивных вызовов.
Факториал (рекурсивное вычисление) на 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 ('')