2016-04-11 6 views
-2

Как я могу реализовать функцию так, чтобы, учитывая число, она вычисляла факториал. Данное число будет большим числом (например, 100!), И я не хочу использовать библиотеку java.math.Эффективно вычислять факториал в 32-разрядной машине

Спасибо!

+0

относительно 'как' часть вашего вопроса У меня есть два простых решения в моем сознании 1. Используя простой цикл, например, factorial (3) будет умножать числа 3, 2 и 1. и 2. используя рекурсивную функцию. –

+0

, пожалуйста, go google it – djechlin

+1

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

ответ

0
  1. Самый большой факториал, который вы можете вычислить и по-прежнему вписываться в подписанное 32-битное целое число - 12!

  2. Для факториалов, которые будут вписываться в 32-разрядное целое число, вы можете использовать любой алгоритм, который вы хотите. Фактически, вы можете даже посмотреть их так, чтобы добиться оптимальной производительности.

Как так

private static int factorial(int n) { 
    final int f[] = { 
     1, 2, 6, 24, 120, 720, 5040, 40320, 
     362880, 3628800, 39916800, 479001600 
    }; 
    if (n < 1 || n > f.length+1) 
     throw new IllegalArgumentException("n"); 
    return f[n-1]; 
} 
+0

Ваша таблица поиска неправильная - вы получаете 13! неправильный - и более того, 13! не вписывается в подписанное 32-битное целое число. –

+0

Да, я обновил его. – vidstige

1

При использовании 32-битных целых чисел, независимо от того, если они подписаны или без знака, наибольшее факториала, которое может быть представлено в 12! = 479001600. Учитывая, что память дешева, эффективная реализация будет таблица поиска:

static final int [] FACTORIALS = 
    {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 
    3628800, 39916800, 479001600 }; 

int factorial(int n) { 
    return FACTORIALS[n]; 
} 

Конечно, вы должны добавить диапазон проверки для n здесь.

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

+0

Вы должны, вероятно, вывести массив на статическую константу; Я бы не ожидал, что Java поделится им между различными прогонами, например, другими языками. –

+0

@LouisWasserman: Правильно, 'final' сам по себе не будет. Изменили код. –

0

Это действительно зависит от того, какой тип данных вы указываете. Помните, что это не количество бит, которое использует ваша машина, даже на 32-битной машине, Java long будет 64 бит.

Если вы выводите либо к int или long, в быстрого способ сделать это просто иметь статический постоянный массив правильных факторных значений и искать ответ там. Это примерно так же дешево, как и получается. Вы можете вручную поместить эти константы, или написать

static final int[] factorials = { 
    1, 
    1, 
    1 * 2, 
    1 * 2 * 3, 
    1 * 2 * 3 * 4, 
    ..., 
    1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12}; 

... и компилятор вычислит эти значения во время компиляции для вас.

Если вы хотите вывести на BigInteger ... это немного интереснее. Guava's BigIntegerMath.factorial делает некоторые интересные вещи здесь; вы можете использовать его или попытаться переопределить его самостоятельно. Переход от 1 до п, ...

  • факторов из полномочий 2, считая их специально, чтобы быть сдвинуты назад в конце
  • умножает на число до точки, где они будут переполнять long, в этот момент он преобразует результат в BigInteger и добавляет его в список
  • разделитель-победитель, умножающий список, если он имеет четыре элемента, a, b, c, d, он будет делать (a * b) * (c * d), поэтому он разбивает список пополам, рекурсивно умножает, а затем умножает результаты.
  • сдвигает назад в степенях 2 в конце