Есть метод, который вычисляет факториал в Java?
Я его еще не нашел. Я что-то пропустил?
Я знаю, что факторный метод является распространенным примером программы для начинающих. Но разве не было бы полезно иметь стандартную реализацию для этого использовать?
Я мог бы использовать такой метод со стандартными типами (int, long...) и с BigInteger / BigDecimal тоже.
26 ответов:
Я не думаю, что было бы полезно иметь библиотечную функцию для факториала. Существует много исследований в области эффективных факторных реализаций. вот несколько реализаций.
Apache Commons Math есть несколько факторных методов в MathUtils класса.
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; }
голые голые факториалы редко нужны на практике. Чаще всего вам понадобится одно из следующих:
1) разделить один факториал на другой, или
2) приближенный ответ с плавающей запятой.
в обоих случаях, вы были бы лучше с простыми пользовательскими решениями.
в случае (1), скажем, если x = 90! / 85!, то вы будете вычислять результат так же, как x = 86 * 87 * 88 * 89 * 90, без необходимости держать 90! на память:)
в случае (2), google для "приближения Стирлинга".
используйте гуавы
BigIntegerMathследующим образом:BigInteger factorial = BigIntegerMath.factorial(n);(функций
intиlongдоступнаIntMathиLongMathсоответственно.)
хотя факториалы делают хорошее упражнение для начинающего программиста, они не очень полезное в большинстве случаев, и все знают, как написать факториальную функцию, поэтому они обычно не находятся в средней библиотеке.
Я считаю, что это будет самый быстрый способ, с помощью таблицы подстановки:
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!разрешено, значимо и правильно.
поскольку факториал растет так быстро, переполнение стека не является проблемой, если вы используете рекурсию. На самом деле, значение 20! является самым большим из них может представлять в Java долго. Таким образом, следующий метод будет либо вычислять факториал(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 потоки
пакет Apache Commons Math имеет метод факторного, Я думаю, вы могли бы использовать это.
короткий ответ: используйте рекурсию.
вы можете создать один метод и вызвать этот метод прямо внутри того же метода рекурсивно:
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); } }
попробуй такое
public static BigInteger factorial(int value){ if(value < 0){ throw new IllegalArgumentException("Value must be positive"); } BigInteger result = BigInteger.ONE; for (int i = 2; i <= value; i++) { result = result.multiply(BigInteger.valueOf(i)); } return result; }
я нашел удивительный трюк, чтобы найти факториалы всего в половине фактических умножений.
пожалуйста, будьте терпеливы, так как это немного длинный пост.
Для Четных Чисел: Чтобы вдвое уменьшить умножение с четными числами, вы получите n/2 фактора. Первым фактором будет число, которое вы принимаете факториал, тогда следующим будет это число плюс это число минус два. Следующий номер будет предыдущим номером плюс последний добавлено число минус два. вы сделали, когда последнее число вы добавили было два (т. е. 2). Это, вероятно, не имеет большого смысла, поэтому позвольте мне привести вам пример.
8! = 8 * (8 + 6 = 14) * (14 + 4 = 18) * (18 + 2 = 20) 8! = 8 * 14 * 18 * 20 which is **40320**обратите внимание, что я начал с 8, затем первое число, которое я добавил, было 6, затем 4, затем 2, каждое добавленное число было на два меньше, чем число, добавленное перед ним. Этот метод эквивалентен умножению наименьших чисел с наибольшими числами, просто с меньшим умножением, например Итак:
8! = 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8! = (1 * 8) * (2 * 7) * (3 * 6) * (4 * 5) 8! = 8 * 14 * 18 * 20просто, не так ли :)
Теперь Для Нечетных Чисел: если число нечетное, сложение такое же, как и в вычитании два каждый раз, но вы останавливаетесь на трех. Однако количество факторов меняется. Если вы разделите число на два ,вы получите некоторое число, заканчивающееся.5. Причина в том, что если мы умножим концы вместе, то у нас останется среднее число. В принципе, все это можно решить, решив для ряда факторов равные к числу, разделенному на два, округляется. Это, вероятно, не имело большого смысла ни для умов без математического фона, так что позвольте мне сделать пример:
9! = 9 * (9 + 7 = 16) * (16 + 5 = 21) * (21 + 3 = 24) * (roundUp(9/2) = 5) 9! = 9 * 16 * 21 * 24 * 5 = **362880**Примечание: Если вам не нравится этот метод, вы также можете просто взять факториал четного числа перед нечетным (восемь в этом случае) и умножить его на нечетное число (т. е. 9! = 8! * 9).
теперь давайте реализуем его в Java:
public static int getFactorial(int num) { int factorial=1; int diffrennceFromActualNum=0; int previousSum=num; if(num==0) //Returning 1 as factorial if number is 0 return 1; if(num%2==0)// Checking if Number is odd or even { while(num-diffrennceFromActualNum>=2) { if(!isFirst) { previousSum=previousSum+(num-diffrennceFromActualNum); } isFirst=false; factorial*=previousSum; diffrennceFromActualNum+=2; } } else // In Odd Case (Number * getFactorial(Number-1)) { factorial=num*getFactorial(num-1); } return factorial; }
isFirstявляется логической переменной объявлен как статический; он используется для 1-го случая, когда мы не хотим изменять предыдущую сумму.попробуйте с четными, а также для нечетных чисел.
Вы можете использовать рекурсию.
public static int factorial(int n){ if (n == 0) return 1; else return(n * factorial(n-1)); }и тогда, после создания метода(функции) выше:
System.out.println(factorial(number of your choice)); //direct example System.out.println(factorial(3));
единственное использование бизнеса для факториала, о котором я могу думать, - это Формулы Erlang B и Erlang C, и не все работают в колл-центре или в телефонной компании. Полезность функции для бизнеса, по - видимому, часто диктует то, что отображается на языке-посмотрите на все функции обработки данных, XML и веб-функций на основных языках.
легко сохранить факториальный фрагмент кода или библиотечную функцию для чего-то подобного.
очень простой метод вычисления факториалов:
private double FACT(double n) { double num = n; double total = 1; if(num != 0 | num != 1){ total = num; }else if(num == 1 | num == 0){ total = 1; } double num2; while(num > 1){ num2 = num - 1; total = total * num2; num = num - 1; } return total; }я использовал double, потому что они могут содержать массивные числа, но вы можете использовать любой другой тип, такой как int, long, float и т. д.
вы также можете использовать рекурсию версия.
static int myFactorial(int i) { if(i == 1) return; else System.out.prinln(i * (myFactorial(--i))); }рекурсия обычно менее эффективна из-за необходимости толкать и поп-рекурсии, поэтому итерация быстрее. С другой стороны, рекурсивные версии используют меньше или нет локальных переменных, что является преимуществом.
Факториал сильно увеличивает дискретное function.So я думаю, что использование BigInteger лучше, чем использование int. Я реализовал следующий код для вычисления факториалов неотрицательных целых чисел.Я использовал рекурсию вместо использования цикла.
public BigInteger factorial(BigInteger x){ if(x.compareTo(new BigInteger("1"))==0||x.compareTo(new BigInteger("0"))==0) return new BigInteger("1"); else return x.multiply(factorial(x.subtract(new BigInteger("1")))); }здесь диапазон больших целых чисел
-2^Integer.MAX_VALUE (exclusive) to +2^Integer.MAX_VALUE, where Integer.MAX_VALUE=2^31.однако диапазон факторного метода, приведенного выше, может быть расширен до двух раз с помощью беззнакового BigInteger.
у нас есть одна строка, чтобы вычислить его:
Long factorialNumber = LongStream.rangeClosed(2, N).reduce(1, Math::multiplyExact);
/** import java liberary class */ import java.util.Scanner; /* class to find factorial of a number */ public class factorial { public static void main(String[] args) { // scanner method for read keayboard values Scanner factor= new Scanner(System.in); int n; double total = 1; double sum= 1; System.out.println("\nPlease enter an integer: "); n = factor.nextInt(); // evaluvate the integer is greater than zero and calculate factorial if(n==0) { System.out.println(" Factorial of 0 is 1"); } else if (n>0) { System.out.println("\nThe factorial of " + n + " is " ); System.out.print(n); for(int i=1;i<n;i++) { do // do while loop for display each integer in the factorial { System.out.print("*"+(n-i) ); } while ( n == 1); total = total * i; } // calculate factorial sum= total * n; // display sum of factorial System.out.println("\n\nThe "+ n +" Factorial is : "+" "+ sum); } // display invalid entry, if enter a value less than zero else { System.out.println("\nInvalid entry!!"); }System.exit(0); } }
нам нужно реализовать итеративно. Если мы реализуем рекурсивно, это вызовет StackOverflow, если вход станет очень большим (т. е. 2 миллиарда). И нам нужно использовать несвязанное число размера, такое как BigInteger, чтобы избежать арифметического переполнения, когда факториальное число становится больше максимального числа данного типа (т. е. 2 миллиарда для int). Вы можете использовать int для максимума 14 факториала и long для максимума 20 факториала перед переполнением.
public BigInteger getFactorialIteratively(BigInteger input) { if (input.compareTo(BigInteger.ZERO) <= 0) { throw new IllegalArgumentException("zero or negatives are not allowed"); } BigInteger result = BigInteger.ONE; for (BigInteger i = BigInteger.ONE; i.compareTo(input) <= 0; i = i.add(BigInteger.ONE)) { result = result.multiply(i); } return result; }Если вы не можете использовать BigInteger, добавьте проверку ошибок.
public long getFactorialIteratively(long input) { if (input <= 0) { throw new IllegalArgumentException("zero or negatives are not allowed"); } else if (input == 1) { return 1; } long prev = 1; long result = 0; for (long i = 2; i <= input; i++) { result = prev * i; if (result / prev != i) { // check if result holds the definition of factorial // arithmatic overflow, error out throw new RuntimeException("value "+i+" is too big to calculate a factorial, prev:"+prev+", current:"+result); } prev = result; } return result; }
цикл while (для небольших количеств)
public class factorial { public static void main(String[] args) { int counter=1, sum=1; while (counter<=10) { sum=sum*counter; counter++; } System.out.println("Factorial of 10 is " +sum); } }
Я получил это от EDX использовать его! его называют рекурсией
public static int factorial(int n) { if (n == 1) { return 1; } else { return n * factorial(n-1); } }
с рекурсией:
public static int factorial(int n) { if(n == 1) { return 1; } return n * factorial(n-1); }с циклом while:
public static int factorial1(int n) { int fact=1; while(n>=1) { fact=fact*n; n--; } return fact; }
Comments