suma - ¿Hay algún método que calcule un factorial en Java?
programas en java de factoriales (26)
No lo encontré, todavía. ¿Me he perdido algo? Sé que un método factorial es un programa de ejemplo común para principiantes. ¿Pero no sería útil tener una implementación estándar para reutilizar? Podría usar dicho método con tipos estándar (int, long ...) y con BigInteger / BigDecimal también.
¡Obtuve esto de EDX! se llama recursión
public static int factorial(int n) {
if (n == 1) {
return 1;
} else {
return n * factorial(n-1);
}
}
Aunque los factoriales son un buen ejercicio para el programador principiante, no son muy útiles en la mayoría de los casos, y todos saben cómo escribir una función factorial, por lo que normalmente no están en la biblioteca promedio.
Creo que esta sería la forma más rápida, mediante una tabla de búsqueda:
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];
}
Para el tipo nativo long
(8 bytes), ¡solo puede contener hasta 20!
20! = 2432902008176640000(10) = 0x 21C3 677C 82B4 0000
Obviamente, 21!
causará desbordamiento
Por lo tanto, para el tipo nativo long
, ¡solo un máximo de 20!
está permitido, significativo y correcto.
Debido a que el factorial crece tan rápido, el desbordamiento de la pila no es un problema si usa recursividad. De hecho, ¡el valor de 20! es el más grande que se puede representar en Java long. Entonces, el siguiente método calculará factorial (n) o arrojará una IllegalArgumentException si n es demasiado grande.
public long factorial(int n) {
if (n > 20) throw new IllegalArgumentException(n + " is out of range");
return (1 > n) ? 1 : n * factorial(n - 1);
}
Otra forma (más genial) de hacer lo mismo es usar la biblioteca de flujo de Java 8 de esta manera:
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);
}
Obtenga más información sobre los factoriales que utilizan las transmisiones de Java 8
El único uso empresarial para un factorial que puedo pensar es en las fórmulas Erlang B y Erlang C, y no todos trabajan en un centro de llamadas o para la compañía telefónica. La utilidad de una función para las empresas parece dictar a menudo lo que aparece en un idioma: observe todas las funciones de manejo de datos, XML y web en los principales idiomas.
Es fácil mantener un fragmento factorial o función de biblioteca para algo como esto.
El paquete Apache Commons Math tiene un método factorial , creo que podrías usarlo.
Encontré un truco increíble para encontrar factoriales en solo la mitad de las multiplicaciones reales.
Por favor, sea paciente ya que es una publicación un poco larga.
Para números pares: para dividir a la mitad la multiplicación con números pares, terminará con n / 2 factores. El primer factor será el número que está tomando el factorial de, luego el siguiente será ese número más ese número menos dos. El siguiente número será el número anterior más el número agregado durado menos dos. Ha terminado cuando el último número que agregó fue dos (es decir, 2) . Eso probablemente no tenía mucho sentido, así que déjame darte un ejemplo.
8! = 8 * (8 + 6 = 14) * (14 + 4 = 18) * (18 + 2 = 20)
8! = 8 * 14 * 18 * 20 which is **40320**
Tenga en cuenta que comencé con 8, luego el primer número que agregué fue 6, luego 4, luego 2, cada número agregado fue dos menos que el número agregado antes. Este método es equivalente a multiplicar los menos números con los números más grandes, solo con menos multiplicación, de esta manera:
8! = 1 * 2 * 3 * 4 * 5 * 6 * 7 *
8! = (1 * 8) * (2 * 7) * (3 * 6) * (4 * 5)
8! = 8 * 14 * 18 * 20
Simple no es eso :)
Ahora para números impares: si el número es impar, la suma es la misma, como en el restar dos cada vez, pero se detiene en tres. Sin embargo, la cantidad de factores cambia. Si divide el número por dos, terminará con un número que termina en .5. La razón es que si multiplicamos los extremos juntos, quedamos con el número medio. Básicamente, todo esto puede resolverse resolviendo por un número de factores igual al número dividido entre dos, redondeado hacia arriba. Probablemente esto tampoco tenía mucho sentido para las mentes sin un trasfondo matemático, así que permítanme hacer un ejemplo:
9! = 9 * (9 + 7 = 16) * (16 + 5 = 21) * (21 + 3 = 24) * (roundUp(9/2) = 5)
9! = 9 * 16 * 21 * 24 * 5 = **362880**
Nota: si no te gusta este método, también puedes tomar el factorial del número par antes del impar (ocho en este caso) y multiplicarlo por el número impar (es decir, 9! = 8! * 9).
Ahora impleméntalo en 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
es una variable booleana declarada como estática; se usa para el primer caso en el que no queremos cambiar la suma anterior.
Pruebe incluso con números impares.
Factorial está aumentando la función discreta. Así que creo que usar BigInteger es mejor que usar int. He implementado el siguiente código para el cálculo del factorial de enteros no negativos. He usado la recursión en lugar de usar un ciclo.
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"))));
}
Aquí el rango del entero grande es
-2^Integer.MAX_VALUE (exclusive) to +2^Integer.MAX_VALUE,
where Integer.MAX_VALUE=2^31.
Sin embargo, el rango del método factorial dado anteriormente se puede extender hasta dos veces utilizando BigInteger sin firmar.
La respuesta corta es: use recursión.
Puede crear un método y llamar a ese método directamente dentro del mismo método recursivamente:
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);
}
}
Los factoriales desnudos desnudos rara vez se necesitan en la práctica. Muy a menudo necesitarás uno de los siguientes:
1) divide un factorial por otro, o
2) respuesta de coma flotante aproximada.
En ambos casos, sería mejor con soluciones personalizadas simples.
En el caso (1), digamos, si x = 90! / 85 !, entonces calculará el resultado igual que x = 86 * 87 * 88 * 89 * 90, ¡sin necesidad de mantener 90! en memoria :)
En el caso (2), google para "aproximación de Stirling".
Necesitamos implementar iterativamente. Si implementamos recursivamente, causará si la entrada se vuelve muy grande (es decir, 2 billones). Y necesitamos usar un número de tamaño sin encuadernar como BigInteger para evitar un desbordamiento aritmático cuando un número factorial se vuelve más grande que el número máximo de un tipo dado (es decir, 2 mil millones para int). Puede usar int para máximo 14 de factorial y largo para máximo 20 de factorial antes del desbordamiento.
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;
}
Si no puede usar BigInteger, agregue una comprobación de errores.
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;
}
No creo que sea útil tener una función de biblioteca para factorial. Hay una buena cantidad de investigación en implementaciones factoriales eficientes. Aquí hay un puñado de implementaciones.
Prueba esto
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;
}
Puedes usar la recursividad.
public static int factorial(int n){
if (n == 0)
return 1;
else
return(n * factorial(n-1));
}
y luego después de crear el método (función) anterior:
System.out.println(factorial(number of your choice));
//direct example
System.out.println(factorial(3));
También puedes usar la versión de recursión.
static int myFactorial(int i) {
if(i == 1)
return;
else
System.out.prinln(i * (myFactorial(--i)));
}
La recursividad generalmente es menos eficiente debido a tener que presionar y hacer estallar las recurrencias, por lo que la iteración es más rápida. Por otro lado, las versiones recursivas usan menos o ninguna variable local, lo que es una ventaja.
Tenemos una sola línea para calcularlo:
Long factorialNumber = LongStream.rangeClosed(2, N).reduce(1, Math::multiplyExact);
Un método bastante simple
for ( int i = 1; i < n ; i++ )
{
answer = answer * i;
}
Un método muy simple para calcular factoriales:
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;
}
He usado el doble porque pueden contener números masivos, pero puedes usar cualquier otro tipo como int, long, float, etc.
PD. Puede que esta no sea la mejor solución, pero soy nuevo en la codificación y me tomó años encontrar un código simple que pudiera calcular los factoriales, así que tuve que escribir el método yo mismo, pero lo estoy poniendo aquí para que pueda ayudar a otras personas como yo. .
Use BigIntegerMath
de Guava de la siguiente manera:
BigInteger factorial = BigIntegerMath.factorial(n);
(Funcionalidad similar para int
y long
está disponible en IntMath
y LongMath
respectivamente.)
con recursión:
public static int factorial(int n)
{
if(n == 1)
{
return 1;
}
return n * factorial(n-1);
}
con while loop:
public static int factorial1(int n)
{
int fact=1;
while(n>=1)
{
fact=fact*n;
n--;
}
return fact;
}
while loop (para números pequeños)
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);
}
}
Apache Commons Math tiene algunos métodos factoriales en la clase MathUtils .
/**
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);
}
}
public class UsefulMethods {
public static long factorial(int number) {
long result = 1;
for (int factor = 2; factor <= number; factor++) {
result *= factor;
}
return result;
}
}
Versión Big Numbers de 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;
}
public int factorial(int num) {
if (num == 1) return 1;
return num * factorial(num - 1);
}
public static int fact(int i){
if(i==0)
return 0;
if(i>1){
i = i * fact(--i);
}
return i;
}