답변:
계승에 대한 라이브러리 기능을 갖는 것이 유용하지 않을 것이라고 생각합니다. 효율적인 팩토리얼 구현에 대한 많은 연구가 있습니다. 다음은 몇 가지 구현입니다.
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의 Big Numbers 버전 :
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 !, 그러면 90을 유지할 필요없이 x = 86 * 87 * 88 * 89 * 90과 같이 결과를 계산합니다! 메모리에 :)
(2)의 경우 "Stirling의 근사치"에 대해 google.
BigIntegerMath다음과 같이 Guava를 사용하십시오 .
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 long에서 나타낼 수있는 가장 큰 것입니다. 따라서 다음 메서드는 factorial (n)을 계산하거나 n이 너무 크면 IllegalArgumentException을 발생시킵니다.
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);
}
}
System.out.println(calc(10));에 System.out.println(calc(Long.MAX_VALUE));당신이 :) 꽤 긴 stactrace을 얻어야한다
BigInteger. 나는 소수점 이하 자릿수 가 8020있는 결과 613578884952214809325384...를 얻은 숫자의 계승을 계산하려고했습니다 27831. 따라서 엄청난 숫자로 작업 할 때조차도 Stackoverflow던져 지지 않을 것입니다. 당연히 맞아요.하지만 실제 사용하면 그렇게 큰 숫자가 있는지 의심 스럽습니다. :-)
이 시도
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;
}
i <= value. for 루프는 (int i = 2; i <= value; i++).
실제 곱셈의 절반에 불과한 계승을 찾는 놀라운 트릭을 찾았습니다.
이것은 약간 긴 게시물이므로 잠시 기다려주십시오.
짝수 : 짝수로 곱셈을 반으로 줄이려면 n / 2 인수로 끝납니다. 첫 번째 요소는 계승을 취하는 숫자이고 다음 요소는 해당 숫자에 2를 더한 숫자입니다. 다음 숫자는 이전 숫자에 마지막으로 추가 된 숫자에서 2를 뺀 숫자입니다. 마지막으로 추가 한 숫자가 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였으며 각 숫자는 이전에 추가 된 숫자보다 2가 적습니다. 이 방법은 다음과 같이 더 적은 곱셈으로 가장 작은 숫자와 가장 큰 숫자를 곱하는 것과 같습니다.
8! = 1 * 2 * 3 * 4 * 5 * 6 * 7 *
8! = (1 * 8) * (2 * 7) * (3 * 6) * (4 * 5)
8! = 8 * 14 * 18 * 20
간단하지 않습니까 :)
이제 홀수 : 숫자가 홀수이면 매번 2를 빼는 것과 같이 더하기는 동일하지만 3에서 멈 춥니 다. 그러나 요인의 수는 변경됩니다. 숫자를 2로 나누면 .5로 끝나는 숫자가됩니다. 그 이유는 끝을 함께 곱하면 중간 숫자가 남기 때문입니다. 기본적으로이 모든 것은 2로 나눈 숫자와 같은 여러 요인을 반올림하여 풀 수 있습니다. 이것은 아마도 수학적 배경이없는 사람에게는별로 이해가되지 않았을 것이므로 예를 들어 보겠습니다.
9! = 9 * (9 + 7 = 16) * (16 + 5 = 21) * (21 + 3 = 24) * (roundUp(9/2) = 5)
9! = 9 * 16 * 21 * 24 * 5 = **362880**
참고 : 이 방법이 마음에 들지 않으면 홀수 앞의 짝수 (이 경우 8)의 계승을 취하고 홀수 (예 : 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정적으로 선언 된 부울 변수입니다. 이전 합계를 변경하지 않으려는 첫 번째 경우에 사용됩니다.
홀수뿐만 아니라 짝수로 시도하십시오.
재귀를 사용할 수 있습니다.
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));
계승을 계산하는 매우 간단한 방법 :
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 등과 같은 다른 유형을 사용할 수 있습니다.
추신 이것은 최선의 해결책이 아닐 수도 있지만 코딩에 익숙하지 않고 계승을 계산할 수있는 간단한 코드를 찾는 데 오랜 세월이 걸렸기 때문에 직접 방법을 작성해야했지만 여기에 넣어서 나와 같은 다른 사람들을 돕습니다. .
Factorial은 이산 함수를 크게 증가시키기 때문에 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.
그러나 위에 주어진 팩토리얼 방법의 범위는 unsigned BigInteger를 사용하여 최대 2 배까지 확장 될 수 있습니다.
이를 계산하는 한 줄이 있습니다.
Long factorialNumber = LongStream.rangeClosed(2, N).reduce(1, Math::multiplyExact);
상당히 간단한 방법
for ( int i = 1; i < n ; i++ )
{
answer = answer * i;
}
/**
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 static int fact(int i){
if(i==0)
return 0;
if(i>1){
i = i * fact(--i);
}
return i;
}
우리는 반복적으로 구현해야합니다. 재귀 적으로 구현하면 입력이 매우 커지면 (예 : 20 억) StackOverflow가 발생합니다. 그리고 계승 수가 주어진 유형의 최대 수 (즉, int의 경우 20 억)보다 커질 때 산술적 오버플로를 방지하기 위해 BigInteger와 같은 바인딩되지 않은 크기 수를 사용해야합니다. 오버플로 전에 최대 14 개의 팩토리얼에 int를 사용하고 최대 20 개의 팩토리얼에 대해 long을 사용할 수 있습니다.
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;
}
동적 프로그래밍을 사용하는 것이 효율적입니다.
그것을 사용하여 반복해서 계산하고 싶다면 (캐싱과 같이)
자바 코드 :
int fact[]=new int[n+1]; //n is the required number you want to find factorial for.
int factorial(int num)
{
if(num==0){
fact[num]=1;
return fact[num];
}
else
fact[num]=(num)*factorial(num-1);
return fact[num];
}
재귀를 사용하는 것이 가장 간단한 방법입니다. N의 계승을 구하려면 N = 1이고 N> 1 인 두 가지 경우를 고려해야합니다. 계승에서는 N, N-1, N-2``를 계속 곱하기 때문에 1까지 N = 0으로 가면 답이 0이됩니다. 팩토리얼이 0에 도달하는 것을 막기 위해 다음과 같은 재귀 방법이 사용됩니다. 계승 함수 내에서 N> 1 인 동안 반환 값은 계승 함수의 다른 시작과 곱해집니다. 이것은 N = 1 케이스에 대해 N = 1에 도달 할 때까지 factorial ()을 재귀 적으로 호출하는 코드를 유지하고, N (= 1) 자체를 반환하고 곱해진 반환 N의 이전에 구축 된 모든 결과는 N으로 곱해집니다. = 1. 따라서 계승 결과를 제공합니다.
static int factorial(int N) {
if(N > 1) {
return n * factorial(N - 1);
}
// Base Case N = 1
else {
return N;
}