Як я можу знайти факторіал додатного числа?


18

Змагання:

Напишіть програму або функцію, яка вводить додатне число і повертає його фактор .

Примітка. Це запитання щодо . Будь ласка, не сприймайте питання та / або відповіді серйозно. Більше інформації тут . Кожне запитання щодо це також питання щодо на , тому виграє найвища відповідь.



4
-1, вибачте, тому що ми отримуємо велику кількість цих питань щодо тролінгу коду, і це насправді не додає їм нічого нового
Doorknob


Кодек-тролінг у процесі видалення, згідно з офіційною позицією. Це запитання має чималу кількість голосів з багатьма відповідями, багато з яких є надзвичайно високо проголосованими. Він отримав трохи більше 50% "видалити" голосів у опитуванні , але він унікальний тим, що отримав так багато відповідей і голосів, тому я фіксую це на історичну значимість.
Дверна ручка

Відповіді:


46

Це дуже проста числова обчислювальна задача, яку ми можемо вирішити з наближенням Стірлінга :

Формула наближення Стірлінга

Як бачимо, ця формула містить квадратний корінь, до якого нам також знадобиться спосіб наближення. Для цього ми оберемо так званий «вавилонський метод» , тому що він, мабуть, найпростіший:

Babylonian method

Зауважте, що обчислення квадратного кореня таким чином є хорошим прикладом рекурсії.

З'єднання все це в програмі Python дає нам таке рішення вашої проблеми:

def sqrt(x, n): # not the same n as below
    return .5 * (sqrt(x, n - 1) + x / sqrt(x, n - 1)) if n > 0 else x

n = float(raw_input())
print (n / 2.718) ** n * sqrt(2 * 3.141 * n, 10)

За допомогою простої модифікації вищевказана програма може вивести акуратну таблицю фабрикантів:

1! =    0.92215
2! =    1.91922
3! =    5.83747
4! =   23.51371
5! =  118.06923
6! =  710.45304
7! = 4983.54173
8! = 39931.74015
9! = 359838.58817

Цей спосіб повинен бути достатньо точним для більшості застосувань.


16
+1 Простота та точність цього методу робить його явним переможцем
Джо Персона

44

C #

Вибачте, але я ненавиджу рекурсивну функцію.

public string Factorial(uint n) {
    return n + "!";
}

1
Технічно ви задовольнили коротке! ;) +1 за коротке зловживання
WallyWest

36

Java

public int factorial ( int n ) {
switch(n){
case 0: return 1;
case 1: return 1;
case 2: return 2;
case 3: return 6;
case 4: return 24;
case 5: return 120;
case 6: return 720;
case 7: return 5040;
case 8: return 40320;
case 9: return 362880;
case 10: return 3628800;
case 11: return 39916800;
case 12: return 479001600;
default : throw new IllegalArgumentException();
}
}

16
Я спробував це - дуже ефективно. Буде доставлено з наступним випуском. :)
Йоганнес

Окрім "синдрому магічних чисел", це насправді може бути хорошою реалізацією, поки n <13, набагато менше стеків. Напишіть його "випадок 4: повернення 4 * 3 * 2;" і ви мали б гідний клас, набагато швидший, ніж старий рекурсивний.
Fabinout

6
@Fabinout, реалізація правильна навіть для n> = 13. 13!> Integer.MAX_VALUE.
emory

21

Пітон

Звичайно, найкращий спосіб вирішити будь-яку проблему - це використовувати регулярні вирази:

import re

# adapted from http://stackoverflow.com/q/15175142/1333025
def multiple_replace(dict, text):
  # Create a regular expression  from the dictionary keys
  regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
  # Repeat while any replacements are made.
  count = -1
  while count != 0:
    # For each match, look-up corresponding value in dictionary.
    (text, count) = regex.subn(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
  return text

fdict = {
    'A': '@',
    'B': 'AA',
    'C': 'BBB',
    'D': 'CCCC',
    'E': 'DDDDD',
    'F': 'EEEEEE',
    'G': 'FFFFFFF',
    'H': 'GGGGGGGG',
    'I': 'HHHHHHHHH',
    'J': 'IIIIIIIIII',
    'K': 'JJJJJJJJJJJ',
    'L': 'KKKKKKKKKKKK',
    'M': 'LLLLLLLLLLLLL',
    'N': 'MMMMMMMMMMMMMM',
    'O': 'NNNNNNNNNNNNNNN',
    'P': 'OOOOOOOOOOOOOOOO',
    'Q': 'PPPPPPPPPPPPPPPPP',
    'R': 'QQQQQQQQQQQQQQQQQQ',
    'S': 'RRRRRRRRRRRRRRRRRRR',
    'T': 'SSSSSSSSSSSSSSSSSSSS',
    'U': 'TTTTTTTTTTTTTTTTTTTTT',
    'V': 'UUUUUUUUUUUUUUUUUUUUUU',
    'W': 'VVVVVVVVVVVVVVVVVVVVVVV',
    'X': 'WWWWWWWWWWWWWWWWWWWWWWWW',
    'Y': 'XXXXXXXXXXXXXXXXXXXXXXXXX',
    'Z': 'YYYYYYYYYYYYYYYYYYYYYYYYYY'}

def fact(n):
    return len(multiple_replace(fdict, chr(64 + n)))

if __name__ == "__main__":
    print fact(7)

1
Звичайно, дійсно :)
П'єр Арло

15

Хаскелл

Короткий код - це ефективний код, тому спробуйте це.

fac = length . permutations . flip take [1..]

Чому це тролінг:

Я б сміявся над будь-яким кодером, який це написав ... Неефективність прекрасна. Можливо, також незрозумілий будь-якому програмісту Haskell, який насправді не може написати факторну функцію.

Редагувати: Я розміщував це деякий час тому, але думав, що уточню для майбутніх людей та людей, які не вміють читати Haskell.

Код тут приймає список чисел від 1 до n, створює список усіх перестановок цього списку і повертає довжину цього списку. На моїй машині це займає близько 20 хвилин на 13 !. І тоді це повинно пройти чотири години на 14! а потім два з половиною дні по 15 !. За винятком того, що в якийсь момент у вас не вистачає пам’яті.

Редагувати 2: Насправді у вас, напевно, не вистачить пам'яті через те, що це Haskell (див. Коментар нижче). Можливо, вам вдасться змусити його оцінити список і залишити його в пам'яті якось, але я не знаю достатньо про оптимізацію (і неоптимізацію) Haskell, щоб точно знати, як це зробити.


Чудовий і в той же час витончений, все одночасно.
PLL

1
Ви впевнені в питанні пам'яті? У будь-якій точці вам потрібно зберегти в пам'яті: - список [1..n]. - Одна конкретна перестановка [1..n], передана громом для решти перестановок (поліном в n). - Акумулятор для lengthфункції.
Іван Дворак

Справедливий пункт, напевно, насправді не так. Не дуже думав про це. Я додам коментар внизу.
jgon

10

C #

Оскільки це математична задача, для цього розрахунку має сенс використовувати додаток, спеціально розроблений для вирішення математичних задач ...

Крок 1:

Встановіть MATLAB. Випробування буде спрацьованим, я думаю, але ця надскладна проблема, ймовірно, досить важлива, щоб заслужити придбання повної версії програми.

Крок 2:

Включіть компонент MATLAB COM у свою програму.

Крок 3:

public string Factorial(uint n) {
    MLApp.MLApp matlab = new MLApp.MLApp();
    return matlab.Execute(String.Format("factorial({0})", n);
}

Matlab для студентів починається від 100 доларів. Професійні версії або ліцензії на сайт можуть перейти в тисячі.
Моше Кац

4
Моше Кац - виправданий тому, що факторіали.
Майк Х.

9

C #

Фактори - математична операція вищого рівня, яку важко переварити за один раз. Найкраще рішення в таких програмових проблемах - розбити одне велике завдання на більш дрібні завдання.

Тепер, н! визначається як 1 * 2 * ... * n, тому, по суті, повторне множення, а множення - це не що інше, як повторне додавання. Отже, маючи на увазі, цю проблему вирішує наступне:

long Factorial(int n)
{
    if(n==0)
    {
        return 1;
    }

    Stack<long> s = new Stack<long>();
    for(var i=1;i<=n;i++)
    {
        s.Push(i);
    }
    var items = new List<long>();
    var n2 = s.Pop();
    while(s.Count >0)
    {
        var n3 = s.Pop();
        items.AddRange(FactorialPart(n2,n3));
        n2 = items.Sum();
    }
    return items.Sum()/(n-1);
}

IEnumerable<long> FactorialPart(long n1, long n2)
{
    for(var i=0;i<n2;i++){
        yield return n1;
    }
}

У вас вузьке вузьке місце надсилає все це через один процесор або ядро, що, я думаю, я вирішив у своїй відповіді :-)
Пол

9
#include <math.h>

int factorial(int n)
{
    const double g = 7;
    static const double p[] = { 0.99999999999980993, 676.5203681218851,
                                -1259.1392167224028, 771.32342877765313,
                                -176.61502916214059, 12.507343278686905,
                                -0.13857109526572012, 9.9843695780195716e-6,
                                1.5056327351493116e-7 };
    double z = n - 1 + 1;
    double x = p[0];
    int i;
    for ( i = 1; i < sizeof(p)/sizeof(p[0]); ++i )
        x += p[i] / (z + i);
    return sqrt(2 * M_PI) * pow(z + g + 0.5, z + 0.5)  * exp(-z -g -0.5) * x + 0.5;
}

Тролі:

  • На 100% правильний спосіб обчислення факторіалу, який повністю пропускає сенс або робити це повторно, або рекурсивно.
  • Ви не маєте поняття, чому це працює, і не могли б узагальнити його, щоб зробити щось інше.
  • Дорожче, ніж просто обчислити його з цілою математикою.
  • Найбільш очевидний "неоптимальний" код ( z = n - 1 + 1) - це власне документування, якщо ви знаєте, що відбувається.
  • Для додаткового тролінгу я повинен обчислити, p[]використовуючи рекурсивний розрахунок коефіцієнтів серії!

(Це наближення Ланцоса до гамма-функції )


Чи є тут якийсь момент - 1 + 1? Мій компілятор оптимізує це (це не номер з плаваючою комою, де оптимізація такого коду могла бути небезпечною), тому він видається непотрібним.
Конрад Боровський

4
@xfix: double z = n - 1є частиною наближення гамма-функції. Це + 1відношення, яке gamma(n + 1) = n!для цілого n.
Бен Джексон

9

Всі ми знаємо з коледжу, що найефективніший спосіб обчислення множення - це використання логарифмів. Зрештою, чому б ще люди використовували таблиці логарифмів протягом сотень років?

Отже, з ідентичності a*b=e^(log(a)+log(b))ми формуємо наступний код Python:

from math import log,exp

def fac_you(x):
    return round(exp(sum(map(log,range(1,x+1)))))

for i in range(1,99):
    print i,":",fac_you(i)

Створюється список чисел від 1до x, ( +1необхідний, тому що Python відсмоктує), обчислює логарифм кожного, підсумовує числа, збільшує е на потужність суми і, нарешті, округляє значення до найближчого цілого числа (тому що Python відсмоктує) . У Python є вбудована функція для обчислення факторіалів, але вона працює лише для цілих чисел, тому не може створювати великі числа (тому що Python смокче). Ось чому необхідна функція вище.

До речі, загальна порада для студентів полягає в тому, що якщо щось не працює так, як очікувалося, це, мабуть, тому, що мова смокче.


Бажаю, щоб я міг дати кілька додаткових голосів за опис, але Python смокче
Mark K Cowan

1
Я сміявся з "fac you"
номер 9

8

На жаль, у Javascript відсутній вбудований спосіб обчислення факторіалу. Але ви можете використовувати його значення в комбінаториці, щоб все-таки визначити значення:

Факториал числа n - це кількість перестановок списку такого розміру.

Отже, ми можемо генерувати кожен список n-значного числа, перевіряти, чи це перестановка, і якщо так, збільшуємо лічильник:

window.factorial = function($nb_number) {
  $nb_trials = 1
  for($i = 0; $i < $nb_number; $i++) $nb_trials *= $nb_number
  $nb_successes = 0
  __trying__:
  for($nb_trial = 0; $nb_trial < $nb_trials; $nb_trial++){
    $a_trial_split = new Array
    $nb_tmp = $nb_trial
    for ($nb_digit = 0; $nb_digit < $nb_number; $nb_digit++){
      $a_trial_split[$nb_digit] = $nb_tmp - $nb_number * Math.floor($nb_tmp / $nb_number)
      $nb_tmp = Math.floor($nb_tmp / $nb_number)
    }
    for($i = 0; $i < $nb_number; $i++)
      for($j = 0; $j < $nb_number; $j++)
        if($i != $j)
          if($a_trial_split[$i] == $a_trial_split[$j])
            continue __trying__
    $nb_successes += 1
  }
  return $nb_successes
}

alert("input a number")
document.open()
document.write("<input type = text onblur = alert(factorial(parseInt(this.value))))>")
document.close()


Тролі:

  • Види угорської позначення, змія_випад і не потрібні сигіли. Наскільки це зло?
  • Придумав власну конвенцію про етикетки стрибків, несумісну з поточним використанням цієї конвенції.
  • Кожна можлива змінна випадково є глобальною.
  • Рішення немає O(n) , не O(n!), але O(n^n). Одного лише цього було б достатньо, щоб тут пройти кваліфікацію.
  • Збільшення числа, а потім перетворення в базу-n є поганим способом формування списку послідовностей. Навіть якби ми хотіли дублікатів. Таємниче розрив при n> 13 - не єдина причина.
  • Звичайно, ми могли використати number.toString(base) , але це не працює для баз вище 36. Так, я знаю 36! це багато , але все - таки ...
  • Я згадав, що у Javascript був оператор модуля? Або Math.pow? Ні? Що ж, добре.
  • Відмова від використання ++за межами for-циклів робить її ще більш загадковою. Також,== погано.
  • Глибоко вкладені безрамкові петлеві конструкції. Також вкладені умовні умови замість AND. Також зовнішнього стану можна було уникнути, закінчивши внутрішню петлю на$i .
  • Функції new Array, document.write(з друзями) таalert (замість рядка або мітки введення) утворюють повний потрійний виграш гріхів вибору функції. Чому введення додається динамічно?
  • Вбудовані обробники подій. О, і глибокі трубопроводи - це пекло налагодження.
  • Атрибути без котирування - це задоволення, а пробіли навколо = їх ще важче читати.
  • Я вже згадував, що ненавиджу крапки з комою?

8

Рубі та Вольфрам Альфа

Це рішення використовує API REST WolframAlpha для обчислення факторіалу, з RestClient для отримання рішення та Nokogiri для його розбору. Він не винаходить жодних коліс і використовує добре перевірені та популярні технології, щоб отримати результат найсучаснішим можливим способом.

require 'rest-client'
require 'nokogiri'

n = gets.chomp.to_i
response = Nokogiri::XML(RestClient.get("http://api.wolframalpha.com/v2/query?input=#{n}!&format=moutput&appid=YOUR_APP_KEY"))
puts response.xpath("//*/moutput/text()").text

7

Javascript

Javascript - це функціональна мова програмування, це означає, що вам доведеться використовувати функції для всього, оскільки його швидше.

function fac(n){
    var r = 1,
        a = Array.apply(null, Array(n)).map(Number.call, Number).map(function(n){r = r * (n + 1);});
    return r;
}

1
Ти можеш пояснити?
Mhmd

7
1 не є функцією. Таким чином, ваш код повільний.
П’єр Арло

4
@ArlaudPierre r = -~(function(){})напевно це вирішить.
nitro2k01

4
Я на робочій машині, тому не дуже хочу встановлювати цю мову. Де я можу знайти версію, яка працюватиме в моєму браузері?
joeytwiddle

3
Мені трохи страшно користуватися Google, оскільки мій бос має обліковий запис у них, і я не хочу, щоб він знав, що я граю в гольф на роботі. Я шукав розширення для Firefox, яке могло б запустити Javascript, але я не можу його знайти. Деякі мої друзі запускають Javascript на jsfiddle.net, але це використовує чужу електроенергію, яка трохи схожа на крадіжку. Моя мама сказала, що я не повинен гуляти з такими людьми, але вони мої друзі, і що я можу зробити? У будь-якому випадку вона іноді приймає більше вершків, ніж потрібно. Дякую за поради, я використовую Ctrl-Shift-J або K у Firefox. Відмова від відповідальності: # comment-trolling
joeytwiddle

5

Використання Bogo-Sort у Java

public class Factorial {
    public static void main(String[] args) {
        //take the factorial of the integers from 0 to 7:
        for(int i = 0; i < 8; i++) {
            System.out.println(i + ": " + accurate_factorial(i));
        }
    }

    //takes the average over many tries
    public static long accurate_factorial(int n) {
        double sum = 0;
        for(int i = 0; i < 10000; i++) {
            sum += factorial(n);
        }
        return Math.round(sum / 10000);
    }

    public static long factorial(int n) {
        //n! = number of ways to sort n
        //bogo-sort has O(n!) time, a good approximation for n!
        //for best results, average over several passes

        //create the list {1, 2, ..., n}
        int[] list = new int[n];
        for(int i = 0; i < n; i++)
            list[i] = i;

        //mess up list once before we begin
        randomize(list);

        long guesses = 1;

        while(!isSorted(list)) {
            randomize(list);
            guesses++;
        }

        return guesses;
    }

    public static void randomize(int[] list) {
        for(int i = 0; i < list.length; i++) {
            int j = (int) (Math.random() * list.length);

            //super-efficient way of swapping 2 elements without temp variables
            if(i != j) {
                list[i] ^= list[j];
                list[j] ^= list[i];
                list[i] ^= list[j];
            }
        }
    }

    public static boolean isSorted(int[] list) {
        for(int i = 1; i < list.length; i++) {
            if(list[i - 1] > list[i])
                return false;
        }
        return true;
    }
}

Це насправді працює, дуже повільно, і це не точно для більшої кількості.


4

PERL

Факторний може бути важкою проблемою. Техніка картографування / зменшення - як і Google, - може розділити математику, відганяючи купу процесів і збираючи результати. Це дозволить добре використати всі ці сердечники або процесори у вашій системі в холодну зимову ніч.

Збережіть як f.perl і chmod 755, щоб переконатися, що ви можете запустити його. У вас встановлений Патологічно еклектичний смітник, чи не так?

#!/usr/bin/perl -w                                                              
use strict;
use bigint;
die "usage: f.perl N (outputs N!)" unless ($ARGV[0] > 1);
print STDOUT &main::rangeProduct(1,$ARGV[0])."\n";
sub main::rangeProduct {
    my($l, $h) = @_;
    return $l    if ($l==$h);
    return $l*$h if ($l==($h-1));
    # arghhh - multiplying more than 2 numbers at a time is too much work       
    # find the midpoint and split the work up :-)                               
    my $m = int(($h+$l)/2);
    my $pid = open(my $KID, "-|");
      if ($pid){ # parent                                                       
        my $X = &main::rangeProduct($l,$m);
        my $Y = <$KID>;
        chomp($Y);
        close($KID);
        die "kid failed" unless defined $Y;
        return $X*$Y;
      } else {
        # kid                                                                   
        print STDOUT &main::rangeProduct($m+1,$h)."\n";
        exit(0);
    }
}

Тролі:

  • forks O (log2 (N)) процесів
  • не перевіряє, скільки у вас процесорів чи ядер
  • Приховує безліч конверсій у форматі bigint / text, які відбуваються в кожному процесі
  • Цикл циклу часто швидше, ніж цей код

ТАК, що в perl ARGV[0]- це фактично перший аргумент, а не сценарій!
ThinkChaos

@plg Я вважаю, що $ 0 може містити назву файлу сценарію, але це не те саме, що $ ARGV [0]
Павло

Так, це я читав. Мені було просто дивно, що в perl це не $ARGV[0]тому, що більшість мов, які я знаю, трохи є там
ThinkChaos

4

Пітон

Просто алгоритм O (n! * N ^ 2) для пошуку факторіалу. Базова справа обробляється. Ніяких переливів.

def divide(n,i):
    res=0
    while n>=i:
         res+=1
         n=n-i
    return res

def isdivisible(n,numbers):
    for i in numbers:
         if n%i!=0:
             return 0
         n=divide(n,i)
    return 1

def factorial(n):
    res = 1
    if n==0: return 1 #Handling the base case
    while not isdivisible(res,range(1,n+1)):
         res+=1
    return res

3

Що ж, у Golfscript є просте рішення. Ви можете використовувати інтерпретатор Golfscript і запустити цей код:

.!+,1\{)}%{*}/

Легко так! Успіхів!


2
Я не знаю GolfScript, але цей мене розчаровує ... На підставі інших прикладів GolfScript на цьому веб-сайті я б очікував, що відповідь буде!
містер Лістер,

1
Це оператор заперечення. 0 стає 1, а все інше стає 0.
Martijn Courteaux

3

Математика

factorial[n_] := Length[Permutations[Table[k, {k, 1, n}]]]

Здається, що для чисел, більших за 11, не працює, а факторіал [11] заморозив мій комп'ютер.


3

Рубін

f=->(n) { return 1 if n.zero?; t=0; t+=1 until t/n == f[n-1]; t }

Найповільніший однолінійний я можу собі уявити. На обчислювач i7 потрібно 2 хвилини 6!.


2

Правильний підхід до цих складних математичних задач - це DSL. Тож я буду моделювати це з точки зору простої мови

data DSL b a = Var x (b -> a)
             | Mult DSL DSL (b -> a)
             | Plus DSL DSL (b -> a)
             | Const Integer (b -> a) 

Щоб добре написати наш DSL, корисно розглядати його як вільну монаду, породжену алгебраїчним функтором

F X = X + F (DSL b (F X)) -- Informally define + to be the disjoint sum of two sets

Ми могли б написати це в Haskell як

Free b a = Pure a
         | Free (DSL b (Free b a))

Я залишу це для читача, щоб отримати тривіальну реалізацію

join   :: Free b (Free b a) -> Free b a
return :: a -> Free b a
liftF  :: DSL b a -> Free b a

Тепер ми можемо розглянути операцію з моделювання факторіалу в цій DSL

factorial :: Integer -> Free Integer Integer
factorial 0 = liftF $ Const 1 id
factorial n = do
  fact' <- factorial (n - 1)
  liftF $ Mult fact' n id

Тепер, коли ми моделювали це, нам просто потрібно надати фактичну функцію інтерпретації нашої вільної монади.

denote :: Free Integer Integer -> Integer
denote (Pure a) = a
denote (Free (Const 0 rest)) = denote $ rest 0
...

А решту позначення я залишу читачеві.

Для покращення читабельності іноді корисно представити конкретний AST форми

data AST = ConstE Integer
         | PlusE AST AST
         | MultE AST AST

а потім право тривіальне відображення

reify :: Free b Integer -> AST

і тоді просто рекурсивно оцінювати AST.


2

Пітон

Нижче представлена ​​версія рішення Python, яка не обмежується обмеженням 32-бітового (або 64-бітного в дуже недавній системі) для цілих чисел у Python. Щоб обійти це обмеження, ми будемо використовувати рядок як вхід і вихід для factorialпідпрограми і внутрішньо розділити рядок на його цифри, щоб мати змогу виконати множення.

Отже, ось код: getDigitsфункція розбиває рядок, що представляє число, на його цифри, тому "1234" стає [ 4, 3, 2, 1 ](зворотний порядок просто робить функцію increaseі multiplyпростішим). increaseФункція приймає такий список є і збільшує його на одиницю. Як випливає з назви, multiplyфункція множиться, наприклад, multiply([2, 1], [3])повертається, [ 6, 3 ]тому що 12 разів 3 - це 36. Це працює так само, як ви б перемножували щось із ручкою та папером.

Потім, нарешті, factorialфункція використовує ці допоміжні функції для обчислення фактичного факторіалу, наприклад, factorial("9")дає "362880"як його вихід.

import copy

def getDigits(n):
    digits = []
    for c in n:
        digits.append(ord(c) - ord('0'))

    digits.reverse()
    return digits

def increase(d):
    d[0] += 1
    i = 0
    while d[i] >= 10:
        if i == len(d)-1:
            d.append(0)

        d[i] -= 10
        d[i+1] += 1
        i += 1

def multiply(a, b):
    subs = [ ]
    s0 = [ ]
    for bi in b:

        s = copy.copy(s0)
        carry = 0
        for ai in a:
            m = ai * bi + carry
            s.append(m%10)
            carry = m//10

        if carry != 0:
            s.append(carry)

        subs.append(s)
        s0.append(0)

    done = False
    res = [ ]
    termsum = 0
    pos = 0
    while not done:
        found = False
        for s in subs:
            if pos < len(s):
                found = True
                termsum += s[pos]

        if not found:
            if termsum != 0:
                res.append(termsum%10)
                termsum = termsum//10
            done = True
        else:
            res.append(termsum%10)
            termsum = termsum//10
            pos += 1

    while termsum != 0:
        res.append(termsum%10)
        termsum = termsum//10

    return res

def factorial(x):
    if x.strip() == "0" or x.strip() == "1":
        return "1"

    factorial = [ 1 ]
    done = False
    number = [ 1 ]
    stopNumber = getDigits(x)
    while not done:
        if number == stopNumber:
            done = True

        factorial = multiply(factorial, number)
        increase(number)

    factorial.reverse()

    result = ""
    for c in factorial:
        result += chr(c + ord('0'))

    return result

print factorial("9")

Примітки

У python ціле число не має обмеження, тому якщо ви хочете зробити це вручну, ви можете просто зробити

fac = 1
for i in range(2,n+1): 
    fac *= i

Є також дуже зручна math.factorial(n)функція.

Це рішення, очевидно, набагато складніше, ніж воно повинно бути, але воно працює, і насправді воно ілюструє, як можна обчислити факторіал, якщо ви обмежені 32 або 64 бітами. Тож поки ніхто не повірить, що це рішення, яке ви придумали для цієї простої (принаймні, в Python) проблеми, ви насправді можете чомусь навчитися.


У Python немає обмежень для цілих чисел ... правда? Можливо, вам доведеться пояснити це краще.
Рікінг

@Riking Так, у python немає обмежень для цілих чисел. Я додав кілька приміток, щоб зробити це більш зрозумілим.
брм

2

Пітон

Найбільш розумне рішення - це чітко перевірити всі числа, поки не знайдете той, який є факторіальним для даного числа.

print('Enter the number')
n=int(input())
x=1
while True:
    x+=1
    tempx=int(str(x))
    d=True
    for i in range(1, n+1):
        if tempx/i!=round(tempx/i):
            d=False
        else:
            tempx/=i
    if d:
        print(x)
        break

2

Найелегантніше рекурсивне рішення в С

Кожен знає, що найелегантніші рішення фабрик є рекурсивними.

Фактор:

0! = 1
1! = 1
n! = n * (n - 1)!

Але множення можна також визначати рекурсивно як послідовні доповнення.

Множення:

n * 0 = 0
n * 1 = n
n * m = n + n * (m - 1)

І так може бути додавання як послідовне збільшення.

Доповнення:

n + 0 = n
n + 1 = (n + 1)
n + m = (n + 1) + (m - 1)

В C, ми можемо використовувати ++xі --xобробляти примітиви (x + 1)і (x - 1)відповідно, тому у нас все визначено.

#include <stdlib.h>
#include <stdio.h>

// For more elegance, use T for the type
typedef unsigned long T;

// For even more elegance, functions are small enough to fit on one line

// Addition
T A(T n, T m) { return (m > 0)? A(++n, --m) : n; }

// Multiplication
T M(T n, T m) { return (m > 1)? A(n, M(n, --m)): (m? n: 0); }

// Factorial
T F(T n) { T m = n; return (m > 1)? M(n, F(--m)): 1; }

int main(int argc, char **argv)
{
    if (argc != 2)
        return 1;

    printf("%lu\n", F(atol(argv[1])));

    return 0;
}

Давайте спробуємо:

$ ./factorial 0
1
$ ./factorial 1
1
$ ./factorial 2
2
$ ./factorial 3
6
$ ./factorial 4
24
$ ./factorial 5
120
$ ./factorial 6
720
$ ./factorial 7
5040
$ ./factorial 8
40320

Ідеально, хоча 8! зайняло багато часу чомусь. Ну добре, що найелегантніші рішення не завжди бувають найшвидшими. Давайте продовжимо:

$ ./factorial 9

Хм, я дам вам знати, коли він повернеться ...


2

Пітон

Як зазначено у відповіді @ Matt_Sieker, фактичні факти можуть бути розбиті на додаток - чому, розбиття завдань є сутністю програмування. Але ми можемо розбити це на додаток на 1!

def complicatedfactorial(n):
    def addby1(num):
        return num + 1
    def addnumbers(a,b):
        copy = b
        cp2 = a
        while b != 0:
            cp2 = addby1(cp2)
            b -= 1
    def multiply(a,b):
        copy = b
        cp2 = a
        while b != 0:
            cp2 = addnumbers(cp2,cp2)
    if n == 0:
        return 1
    else:
        return multiply(complicatedfactorial(n-1),n)

Я думаю, що цей код гарантує SO-помилку, оскільки

  1. Рекурсія - зігріває її

  2. Кожен шар генерує дзвінки для множення

  3. що генерує дзвінки до номерів

  4. що генерує дзвінки до addby1!

Занадто багато функцій, правда?



1

TI-Basic 84

:yumtcInputdrtb@gmail And:cReturnbunchojunk@Yahoo A!op:sEnd:theemailaddressIS Crazy ANSWER LOL

Це справді працює :)


1

Javascript

Очевидно, що робота програміста - зробити якомога менше роботи та використовувати якомога більше бібліотек. Тому ми хочемо імпортувати jQuery і math.js . Тепер завдання просте так:

$.alert=function(message){
    alert(message);
}$.factorial=function(number){
    alert(math.eval(number+"!"));
    return math.eval(number+"!");
}
$.factorial(10);

1

Пітон

При незначній модифікації стандартної рекурсивної факторної реалізації вона стає нестерпно повільною для n> 10.

def factorial(n):
    if n in (0, 1):
        return 1
    else:
        result = 0
        for i in range(n):
            result += factorial(n - 1)
        return result

1

Баш

#! /bin/bash

function fact {
    if [[ ${1} -le 1 ]]; then
        return 1
    fi;

    fact $((${1} - 1))
    START=$(date +%s)
    for i in $(seq 1 $?); do sleep ${1}; done
    END=$(date +%s)
    RESULT=$(($END - $START))
    return $RESULT
}

fact ${1}
echo $?

1

Спробуємо зробити це методом Монте-Карло . Усі ми знаємо, що ймовірність двох випадкових n -перерахунків рівна рівно 1 / n! . Тому ми можемо просто перевірити, скільки тестів потрібно (назвемо це число b ), поки не отримаємо c балів. Тоді, н! ~ б / с .

Sage, теж повинен працювати в Python

def RandomPermutation(n) :           
    t = range(0,n)                   
    for i in xrange(n-1,0,-1):       
        x = t[i]                     
        r = randint(0,i)             
        t[i] = t[r]                  
        t[r] = x                     
    return t                         

def MonteCarloFactorial(n,c) :   
    a = 0                            
    b = 0                            
    t = RandomPermutation(n)         
    while a < c :                
        t2 = list(t)                 
        t = RandomPermutation(n)     
        if t == t2 :                 
            a += 1                   
        b += 1                       
    return round(b/c)            

MonteCarloFactorial(5,1000)
# returns an estimate of 5!

1

баш

Факториали легко визначити за допомогою добре відомих інструментів командного рядка з bash.

read -p "Enter number: " $n
seq 1 $n | xargs echo | tr ' ' '*' | bc

Як @Aaron Davies згадував у коментарях, це виглядає набагато акуратніше, і всі ми хочемо приємної та охайної програми, чи не так?

read -p "Enter number: " $n
seq 1 $n | paste -sd\* | bc

1
я рекомендую сильно занижену pasteкоманду:seq 1 $n | paste -sd\* | bc
Аарон Девіс

2
@AaronDavies pasteвиглядає як звичайне англійське слово і цим легко запам'ятовується. Ми справді цього хочемо? ; o)
jippie
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.