Факториал Java возвращает 0

Я сделал простую функцию для вычисления факториала числа, но из числа 34 возвращает 0 . Он должен быть с номера 51.

   public class Métodos {
       public int factorial (int numero ){

          if ((numero <0)||(numero>50)){

           return 0;        
          } 

          else if ((numero == 0)||(numero == 1)){

           return 1;   
          }

          else{

           return numero * factorial(numero -1); 


          }

    }




    }

Спасибо !

Редактировать:

Хорошо, как я могу это проверить?

потому что он говорит, что int не может быть преобразован в bigInteger.

 public static void main(String[] args) {
        // TODO code application logic here
         Métodos metod = new Métodos();
         System.out.print("El resultado es : " + metod.factorial(-12)+ "\n");
         System.out.print("El resultado es : " + metod.factorial(-1)+ "\n");
         System.out.print("El resultado es : " + metod.factorial(0)+ "\n");
         System.out.print("El resultado es : " + metod.factorial(1)+ "\n");
         System.out.print("El resultado es : " + metod.factorial(5)+ "\n");
         System.out.print("El resultado es : " + metod.factorial(51)+ "\n");
         System.out.print("El resultado es : " + metod.factorial(520)+ "\n");
    }

person user3325719    schedule 13.04.2014    source источник


Ответы (4)


Факториал 34 равен примерно 3*1038 — он не помещается в int, который может содержать числа до 2*109. Стоимость 34! не поместится даже в long.

Если вам нужно вычислить факториалы таких больших чисел, используйте BigInteger класс. Объекты этого класса могут содержать целые значения произвольного размера. Обратите внимание, что операции будут выполняться не с помощью инфиксных операторов, а с помощью методов:

public BigInteger factorial (int numero ){
    if (numero < 0) {
        return BigInteger.ZERO;
    } else if (numero==0){
        return BigInteger.ONE;
    } else {
        return BigInteger.valueOf(numero).multiply(factorial(numero-1));
    }
}
person Sergey Kalinichenko    schedule 13.04.2014
comment
Спасибо. Я отредактировал вопрос. Не могли бы вы взглянуть? - person user3325719; 14.04.2014

Факториалы очень быстро становятся большими. Тип данных int, который вы используете, слишком мал для хранения огромных чисел, которые получаются в результате. Вы можете хранить до 12! в int. Переключитесь на long, и вы сможете сохранить до 20!. Вам нужно будет использовать BigInteger, чтобы выйти за рамки что.

Причина, по которой каждый результат равен 0, начиная с 34!, заключается в том, что 34! является:

295232799039604140847618609643520000000

Простые множители этого числа:

232 × 315 × 57 × 74 × 113 × 132 × 172 × 19 × 23 × 29 × 31

Обратите внимание, что простая факторизация имеет 32 двойки. Это означает, что при записи в двоичном формате число заканчивается ровно на 32 нуля:

1101111000011011110001001101000110011110111111001010110010000010
0100010001011101101001110101101100000000000000000000000000000000

Поскольку int имеет ширину всего 32 бита, он содержит только младшие 32 бита этого числа, которые все равны 0, а int со всеми битами 0 представляет числовое значение 0.

(Выше я упомянул, что на самом деле это происходит раньше; правильный результат переполняет int после 12!. Однако простой факт умножения заключается в том, что при умножении двух чисел цифры в числах не могут влиять на цифры результата в более низкой позиции; только цифры в той же или более высокой позиции. Например, умножьте любые два длинных числа, которые оба заканчиваются на 4. Результат должен заканчиваться на 6, независимо от того, какими были полные числа. Это означает, что даже после того, как вычисление факториала переполняет int, все младшие 32 бита все еще правильно!)

После 34! каждый факториал будет иметь по крайней мере 32 двойки в своей простой факторизации (поскольку он просто кратен предыдущему факториалу), поэтому, когда правильные значения обрезаются, чтобы поместиться в int, они будут все равно 0. Другой способ взглянуть на это так: после 34! каждый факториал вычисляется как 0, потому что он просто кратен ранее вычисленному 0.

person Boann    schedule 13.04.2014
comment
Спасибо. Я отредактировал вопрос. Не могли бы вы взглянуть? - person user3325719; 14.04.2014

1- Я носитель португальского языка, и, пожалуйста, следуйте моему совету: "Пишите код на английском языке". Миру легче читать, и когда вы доберетесь до соглашений, ваши методы будут иметь имена, такие как getSomething() или setSomething(something).

2- О вашей проблеме. Пытаться:

for (int i = 0 ; i < 60; i++){
    System.out.println(i + " " + factorial(i));
}

Вы увидите, что около 12 вы начинаете получать странные значения, потому что int в java ограничен 2 ^ 31-1, и вы получаете переполнения: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html

Можно попробовать долго. Но и это переполнится задолго до 51.

Вам придется использовать класс BigInteger, который обрабатывает произвольные значения.

public static BigInteger factorial(BigInteger number) {
    if ((number.compareTo(BigInteger.ZERO) == 0)
            || (number.compareTo(BigInteger.ONE) == 0)) {
        return BigInteger.ONE;
    } else {
        return number.multiply(factorial(number.subtract(BigInteger.ONE)));
    }
}
person gfelisberto    schedule 13.04.2014
comment
Спасибо за совет . - person user3325719; 14.04.2014

Java int — это примитивный тип со знаком, хранящийся в 32 битах, что означает, что он имеет допустимый диапазон от -231 до 231-1 (см. также Integer.MIN_VALUE и Integer.MAX_VALUE). В Java 8+ вы можете вычислить факториал, используя лямбды и взяв диапазон значений int от 2 до n, сопоставив их с BigInteger, а затем сокращение значений с умножением; Нравиться

public static BigInteger factorial(int n) {
    if (n < 0) {
        return BigInteger.ZERO;
    }
    return IntStream.rangeClosed(2, n).mapToObj(BigInteger::valueOf) //
            .reduce(BigInteger.ONE, (a, b) -> a.multiply(b));
}
person Elliott Frisch    schedule 07.05.2017