Mensagem de erro “número inteiro muito grande” para 600851475143

89
public class Three {
    public static void main(String[] args) {
        Three obj = new Three();
        obj.function(600851475143);
    }

    private Long function(long  i) {
        Stack<Long> stack = new Stack<Long>();

        for (long j = 2; j <= i; j++) {
            if (i % j == 0) {
                stack.push(j);
            }
        }
        return stack.pop();
    }
}

Quando o código acima é executado, ele produz um erro na linha obj.function(600851475143);. Por quê?

user446654
fonte
1
também não há diferença entre "l" e "L"?
user446654
@ user446654: Não, existe. O último é mais legível. Leia "Java Puzzler" para isso.
Adeel Ansari
@ user446654: desenvolvendo pensamentos de @Thilo sobre possível limite de memória excedendo Eu quero adicionar minhas 2 moedas: você escolheu um algoritmo muito, muito ruim para pesquisar todos os divisores de um número se quiser operar com números tão grandes como no seu exemplo. Algo baseado em programação dinâmica provavelmente funcionaria melhor. Google sobre isso para obter mais resultados.
Romano de
1
Tag PE adicionada, Projeto Euler # 3
st0le
@ st0le: IMHO, a questão deffinitely não é sobre a solução original do problema, e o que vemos também não é uma solução.
Romano de

Respostas:

201

600851475143não pode ser representado como um número inteiro de 32 bits (tipo int). Ele pode ser representado como um número inteiro de 64 bits (tipo long). literais longos em Java terminam com um "L":600851475143L

Yuliy
fonte
72

Acrescentar sufixo L: 23423429L.

Por padrão, o java interpreta todos os literais numéricos como valores inteiros de 32 bits. Se você deseja especificar explicitamente que é algo maior que um inteiro de 32 bits, você deve usar o sufixo Lpara valores longos.

romano
fonte
Para aqueles que procuram uma explicação mais completa do motivo pelo qual você recebe esta mensagem de erro mesmo depois de alterar o tipo de variável para long, leia isto: stackoverflow.com/a/8924925/293280
Joshua Pinter
29

Você precisa usar um literal longo:

obj.function(600851475143l);  // note the "l" at the end

Mas espero que essa função fique sem memória (ou tempo) ...

Thilo
fonte
17
considera-se uma prática melhor l1
usar letras
2
@Bozho: Concordo. Mas eu tenho um background em Perl. Eu codifico "somente gravação" :-)
Thilo
Use "L" em vez de "l"
Kevin V
13

O compilador java tenta interpretar 600851475143 como um valor constante do tipo int por padrão. Isso causa um erro, pois 600851475143 não pode ser representado com um int.

Para dizer ao compilador que você deseja que o número seja interpretado como longo, você deve adicionar um lou Ldepois dele. Seu número deve ficar assim600851475143L .

Uma vez que algumas fontes tornam difícil distinguir "1" e "l" minúsculo, você deve sempre usar o "L" maiúsculo.

Josefx
fonte
6

Você precisa de 40 bits para representar o literal inteiro 600851475143. Em Java, o valor inteiro máximo é 2 ^ 31-1 no entanto (ou seja, os inteiros são de 32 bits, consulte http://download.oracle.com/javase/1.4.2/docs /api/java/lang/Integer.html ).

Isso não tem nada a ver com function. Tente usar um literal inteiro longo (como sugerido nas outras respostas).

Andre Holzner
fonte
4

Em tempo de compilação, o número "600851475143" é representado em um inteiro de 32 bits, tente literal longo no final do seu número para superar este problema.

JVM
fonte
3

Além de todas as outras respostas, o que você pode fazer é:

long l = Long.parseLong("600851475143");

por exemplo :

obj.function(Long.parseLong("600851475143"));
Anand Undavia
fonte
1

Ou você pode declarar o número de entrada contanto que ele faça o código tango: D ...

public static void main(String[] args) {

    Scanner in = new Scanner(System.in);
    System.out.println("Enter a number");
    long n = in.nextLong();

    for (long i = 2; i <= n; i++) {
        while (n % i == 0) {
            System.out.print(", " + i);
            n /= i;
        }
    }
}
Milen.Jeremic
fonte