Преобразование очень большого целого числа в битовый вектор завершается неудачно

import java.math.BigInteger;
import java.util.ArrayList;

public class Factorial {

    public static int[] bitVector(int n) {
        ArrayList<Integer> bitList = new ArrayList<Integer>();
        BigInteger input = computeFactorial(n);
        System.out.println(input);
        BigInteger[] result = input.divideAndRemainder(new BigInteger(String.valueOf(2)));
        if (result[0].intValue()==0) {return new int[]{result[1].intValue()};}
        else {
            bitList.add(result[1].intValue());
        }
        while(result[0].intValue() != 0) {
            result = result[0].divideAndRemainder(new BigInteger(String.valueOf(2)));
            bitList.add(result[1].intValue());
        }
        int[] array = new int[bitList.size()];
        for (int i=0; i<array.length; i++) {
            array[i]=bitList.get(i).intValue();
        }
        return array;
    }

    public static BigInteger computeFactorial(int n) {
        if (n==0) {
            return new BigInteger(String.valueOf(1));
        } else {
            return new BigInteger(String.valueOf(n)).multiply(computeFactorial(n-1));
        }
    }

    public static void main(String[] args) {
        int[] bitVector = bitVector(35);
        for (int bit: bitVector)
        System.out.print(bit+" ");
        System.out.println();
    }
}

Код выше работает нормально, когда вход bitVector не больше чем 35, Тем не менее, когда я прохожу 36 в качестве параметра для bitVectorвсе, кроме одного бита, ушли в вывод.

Я потенциально исключил следующие причины:

  1. Это может не иметь ничего общего с типом BigInteger, так как он был спроектирован так, чтобы никогда не переполняться.

  2. Это не может быть связано с использованием памяти программой, которая использует только 380M во время выполнения.

  3. Я распечатываю значение computeFactorial(36), который выглядит хорошо.

Что на земле происходит там?

2 ответа

Решение

Итак, что вы пытаетесь сделать, это

public static String factorialAsBinary(int n) {
    BigInteger bi = BigInteger.ONE;
    for (; n > 1; n--)
        bi = bi.multiply(BigInteger.valueOf(n));
    return bi.toString(2);
}

public static void main(String... args) {
    String fact36 = factorialAsBinary(36);
    for (char ch : fact36.toCharArray())
        System.out.print(ch + " ");
    System.out.println();
}

который печатает

1 0 0 0 1 0 0 0 1 0 1 0 0 1 1 0 0 0 0 1 0 1 0 1 1 0 0 1 0 1 1 0 1 1 1 1 0 1 1 1 0 1 0 1 0 0 0 0 0 1 1 1 0 1 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 1 0 1 0 0 0 0 1 1 1 1 1 0 0 1 1 1 1 0 0 1 1 1 0 1 1 0 0 1 1 1 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

Что на земле происходит там?

Ваш код намного сложнее, чем должен быть, что также облегчает ошибки и затрудняет понимание.

result[0].intValue() неправильно:

intValue ():

Преобразует этот BigInteger в Int. Это преобразование аналогично сужающему примитивному преобразованию из long в int, как определено в Спецификации языка Java: если этот BigInteger слишком велик, чтобы поместиться в int, возвращаются только младшие 32 бита. Обратите внимание, что это преобразование может потерять информацию об общей величине значения BigInteger, а также вернуть результат с обратным знаком.

в вашем случае он возвращает младшие 32 бита, которые равны нулю, поэтому вы возвращаете 0 после первого деления

Другие вопросы по тегам