programing

Java에서 계수를 계산하는 방법이 있나요?

nicescript 2022. 12. 29. 21:57
반응형

Java에서 계수를 계산하는 방법이 있나요?

아직 못 찾았어요.제가 뭔가를 빠뜨렸나요?나는 요인법이 초보자를 위한 일반적인 예시 프로그램이라는 것을 알고 있다.하지만 이것을 재사용할 수 있는 표준 구현이 있으면 유용하지 않을까요?표준 타입(예: int, long...)이나 BigInteger/BigDecimal에서도 사용할 수 있습니다.

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!인 경우, 90!을 메모리에 고정할 필요 없이 x = 86 * 87 * 88 * 89 * 90으로 결과가 계산됩니다. : )

(2)의 경우는, 「스틸링의 근사치」를 검색해 주세요.

다음과 같이 Guava를 사용합니다.

BigInteger factorial = BigIntegerMath.factorial(n);

(동일한 기능:int그리고.long는 및 에서 각각 사용할 수 있습니다.)

요인식은 초보 프로그래머에게는 좋은 연습이 되지만 대부분의 경우 유용하지 않고 모든 사람이 요인 함수를 작성하는 방법을 알고 있기 때문에 일반적으로 평균 라이브러리에는 없습니다.

이것이 룩업 테이블에서 가장 빠른 방법이라고 생각합니다.

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바이트), 최대 8바이트까지만 유지할 수 있습니다.20!

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

물론. 뻔하지.21!오버플로를 일으킵니다.

따라서 네이티브 타입의 경우long, 최대값만20!허용되고, 의미가 있으며, 정확합니다.

요인이 빠르게 증가하므로 재귀를 사용하는 경우 스택 오버플로는 문제가 되지 않습니다.사실, 20!의 값은 Java long에서 나타낼 수 있는 가장 큰 값입니다.따라서 다음 메서드는 요인(n)을 계산하거나 Ilgal Argument를 던집니다.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의 스트림을 사용한 팩터ial에 대한 자세한 내용은 이쪽

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;
}

재귀를 사용할 수 있습니다.

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));

나는 실제 곱셈의 절반에서 인자를 찾는 놀라운 기술을 발견했다.

조금 긴 글이니 조금만 기다려 주세요.

짝수:짝수로 곱셈을 반으로 나누려면 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로 나누면 0.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는 스태틱으로 선언된 부울 변수입니다.이전 합계를 변경하지 않는 첫 번째 경우에 사용됩니다.

홀수뿐만 아니라 짝수로도 시도합니다.

제가 생각할 수 있는 유일한 비즈니스 용도는 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;
}

큰 숫자를 넣을 수 있기 때문에 더블을 사용하고 있습니다만, int, long, float 등 다른 타입은 사용할 수 있습니다.

추신: 이것이 최선의 해결책은 아닐지 모르지만, 저는 코딩에 익숙하지 않아서, 계수를 계산할 수 있는 간단한 코드를 찾는 데 오랜 시간이 걸려서 제가 직접 방법을 써야 했지만, 저 같은 사람들에게 도움이 되기 위해 이 방법을 여기에 붙입니다.

재귀 버전도 사용할 수 있습니다.

static int myFactorial(int i) {
    if(i == 1)
        return;
    else
        System.out.prinln(i * (myFactorial(--i)));
}

재귀는 일반적으로 반복을 푸시 및 팝해야 하므로 효율성이 떨어집니다. 따라서 반복이 더 빠릅니다.반면 재귀 버전에서는 로컬 변수를 적게 사용하거나 사용하지 않는 것이 유리합니다.

우리는 반복적으로 실행할 필요가 있다.재귀적으로 구현하면 입력이 매우 커지면 StackOverflow가 발생합니다(즉, 20억).또한 BigInteger와 같은 바인딩되지 않은 크기 숫자를 사용하여 요인 수가 주어진 유형의 최대 수보다 클 때 산술적 오버플로를 방지해야 합니다(즉, int의 경우 20억).오버플로우 전에 최대 요인 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;
}

요인은 매우 증가하는 이산 함수입니다.그래서 저는 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를 사용하여 최대 두 배까지 확장할 수 있습니다.

계산은 1줄로 되어 있습니다.

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;
}
public int factorial(int num) {
        if (num == 1) return 1;
        return num * factorial(num - 1);
}

while loop(소수의 경우)

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;
}

재귀가 가장 간단한 방법입니다.N의 계수를 찾으려면 N = 1과 N > 1인 두 경우를 고려해야 한다. 왜냐하면 요인에서는 1까지 N, N-1, N-2…를 곱하기 때문이다. N= 0으로 가면 답이 0이 된다.요인이 0에 도달하는 것을 멈추기 위해 다음과 같은 재귀적 방법을 사용합니다.요인 함수 내에서 N>1인 동안 반환 값은 요인 함수의 다른 시작과 곱됩니다.이렇게 하면 코드가 N=1에 도달할 때까지 반복적으로 factory()를 호출하는 것을 유지할 수 있습니다. N=1의 경우 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;
    }

public static long factorial(int number) {
    if (number < 0) {
        throw new ArithmeticException(number + " is negative");
    }
    long fact = 1;
    for (int i = 1; i <= number; ++i) {
        fact *= i;
    }
    return fact;
}

재귀 사용.


public static long factorial(int number) {
    if (number < 0) {
        throw new ArithmeticException(number + " is negative");
    }
    return number == 0 || number == 1 ? 1 : number * factorial(number - 1);
}

원천

Java 9+ 를 사용하면, 이 솔루션을 사용할 수 있습니다.이것은 많은 숫자를 보유하기에 이상적인 BigInteger를 사용합니다.

...    
import java.math.BigInteger;
import java.util.stream.Stream;
...

String getFactorial(int n) {
    return Stream.iterate(BigInteger.ONE, i -> i.add(BigInteger.ONE)).parallel() 
            .limit(n).reduce(BigInteger.ONE, BigInteger::multiply).toString();
}

동적 프로그래밍을 사용하면 효율적입니다.

(캐싱과 같이) 몇 번이고 계산하기 위해 사용할 경우

자바 코드:

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];
 }

언급URL : https://stackoverflow.com/questions/891031/is-there-a-method-that-calculates-a-factorial-in-java

반응형