Как мне найти факториал положительного числа?


18

Соревнование:

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

Примечание: это вопрос . Пожалуйста, не воспринимайте вопрос и / или ответы всерьез. Больше информации здесь . Каждый вопрос о также является вопросом о , поэтому побеждает ответ, получивший наибольшее количество голосов.



4
-1, извините, потому что мы получаем огромный поток этих вопросов троллинга кода, и это на самом деле не добавляет им ничего нового
Doorknob


Код-троллинг находится в процессе удаления согласно официальной позиции. Этот вопрос имеет достаточное количество голосов со многими ответами, многие из которых чрезвычайно высоко проголосовали. Он получил чуть более 50% «исключенных» голосов в опросе , но он уникален тем, что получил так много ответов и голосов, поэтому я фиксирую его на историческом значении.
Дверная ручка

Ответы:


46

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

Stirling's approximation formula

Как видите, эта формула имеет квадратный корень, который нам также понадобится приблизить. Для этого мы выберем так называемый «вавилонский метод» , потому что он, пожалуй, самый простой:

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

Джава

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.
Эмори

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

Haskell

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

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

Почему это троллинг:

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

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

Код здесь берет список чисел от 1 до n, создает список всех перестановок этого списка и возвращает длину этого списка. На моей машине это занимает около 20 минут за 13! И тогда это должно занять четыре часа на 14! а потом два с половиной дня по 15 !. За исключением того, что в какой-то момент у вас заканчивается память.

Редактировать 2: На самом деле вам, вероятно, не хватит памяти из-за того, что это Хаскелл (см. Комментарий ниже). Возможно, вы сможете заставить его оценить список и каким-то образом сохранить его в памяти, но я недостаточно знаю об оптимизации (и неоптимизации) 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 отстой). Вот почему вышеупомянутая функция необходима.

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


Хотел бы я дать несколько дополнительных голосов за описание, но Питон отстой
Марк К Коуэн

1
Я смеялся над "
лицом к лицу

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()


Тролли:

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

8

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

Это решение использует REST API 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. Отказ от ответственности: # комментарий-троллинг
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);
    }
}

Тролли:

  • форкс O (log2 (N)) процессов
  • не проверяет, сколько у вас процессоров или ядер
  • Скрывает много преобразований bigint / text, которые происходят в каждом процессе
  • Цикл for часто быстрее, чем этот код

TIL, что в Perl ARGV[0]на самом деле первый аргумент, а не сценарий!
ThinkChaos

@plg Я думаю, что $ 0 может содержать имя файла сценария, но это не то же самое, что $ ARGV [0]
Paul

Да, это то, что я прочитал. Просто мне показалось удивительным, что в 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.
Мартейн Курто


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

@Riking Да, в python нет предела для целых чисел. Я добавил несколько заметок, чтобы было понятнее.
BRM

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

Самое элегантное рекурсивное решение в C

Каждый знает, что самые элегантные решения для факториалов рекурсивны.

Факториал:

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 Error, потому что

  1. Рекурсия - согревает

  2. Каждый слой генерирует призывы к умножению

  3. который генерирует звонки на addnumbers

  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 хитов. Тогда н! ~ б / с .

Мудрец, должен работать и в 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выглядит как обычное английское слово, и его легко запомнить. Мы действительно этого хотим? ; о)
Джиппи
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.