Есть ли метод, который вычисляет факториал в Java? - PullRequest
92 голосов
/ 21 мая 2009

Я еще не нашел его. Я что-то пропустил? Я знаю, что метод факториала является распространенным примером программы для начинающих. Но не будет ли полезно иметь стандартную реализацию для повторного использования? Я мог бы использовать такой метод со стандартными типами (int, long ...) и с BigInteger / BigDecimal тоже.

Ответы [ 27 ]

53 голосов
/ 21 мая 2009

Apache Commons Math имеет несколько факторных методов в классе MathUtils .

39 голосов
/ 24 октября 2011
public class UsefulMethods {
    public static long factorial(int number) {
        long result = 1;

        for (int factor = 2; factor <= number; factor++) {
            result *= factor;
        }

        return result;
    }
}

версия больших чисел HoldOffHunger :

public static BigInteger factorial(BigInteger number) {
    BigInteger result = BigInteger.valueOf(1);

    for (long factor = 2; factor <= number.longValue(); factor++) {
        result = result.multiply(BigInteger.valueOf(factor));
    }

    return result;
}
25 голосов
/ 21 мая 2009

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

22 голосов
/ 21 мая 2009

Голые голые факториалы редко нужны на практике. Чаще всего вам понадобится одно из следующих:

1) разделить один факториал на другой или

2) приблизительный ответ с плавающей точкой.

В обоих случаях вам будет проще с простыми индивидуальными решениями.

В случае (1), скажем, если х = 90! / 85 !, тогда вы вычислите результат как x = 86 * 87 * 88 * 89 * 90, без необходимости удерживать 90 в памяти:)

В случае (2), Google для "приближения Стерлинга".

11 голосов
/ 19 февраля 2013

Используйте Guava's BigIntegerMath следующим образом:

BigInteger factorial = BigIntegerMath.factorial(n);

(Аналогичные функции для int и long доступны в IntMath и LongMath соответственно.)

6 голосов
/ 05 ноября 2014

Поскольку факториал растет очень быстро, переполнение стека не является проблемой, если вы используете рекурсию. На самом деле значение 20! является крупнейшим из представленных в Java. Поэтому следующий метод будет либо вычислять factorial (n), либо генерировать исключение IllegalArgumentException, если n слишком велико.

public long factorial(int n) {
    if (n > 20) throw new IllegalArgumentException(n + " is out of range");
    return (1 > n) ? 1 : n * factorial(n - 1);
}

Еще один (круче) способ сделать то же самое - использовать потоковую библиотеку Java 8 следующим образом:

public long factorial(int n) {
    if (n > 20) throw new IllegalArgumentException(n + " is out of range");        
    return LongStream.rangeClosed(1, n).reduce(1, (a, b) -> a * b);
}

Подробнее о Факториалы с использованием потоков Java 8

6 голосов
/ 20 июля 2013

Я считаю, что это будет самый быстрый способ, с помощью таблицы поиска:

private static final long[] FACTORIAL_TABLE = initFactorialTable();
private static long[] initFactorialTable() {
    final long[] factorialTable = new long[21];
    factorialTable[0] = 1;
    for (int i=1; i<factorialTable.length; i++)
        factorialTable[i] = factorialTable[i-1] * i;
    return factorialTable;
}
/**
 * Actually, even for {@code long}, it works only until 20 inclusively.
 */
public static long factorial(final int n) {
    if ((n < 0) || (n > 20))
        throw new OutOfRangeException("n", 0, 20);
    return FACTORIAL_TABLE[n];
}

Для нативного типа long (8 байт) он может содержать до 20!

.
20! = 2432902008176640000(10) = 0x 21C3 677C 82B4 0000

Очевидно, 21! вызовет переполнение.

Следовательно, для нативного типа long допустимо, значимо и правильно только максимум 20!.

6 голосов
/ 22 мая 2013

Краткий ответ: используйте рекурсию.

Вы можете создать один метод и вызвать этот метод прямо внутри того же метода:

public class factorial {

    public static void main(String[] args) {
        System.out.println(calc(10));
    }

    public static long calc(long n) {
        if (n <= 1)
            return 1;
        else
            return n * calc(n - 1);
    }
}
6 голосов
/ 21 мая 2009

В пакете Apache Commons Math есть факторный метод , я думаю, вы могли бы использовать это.

5 голосов
/ 21 мая 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...