Komunikat o błędzie „Zbyt duża liczba całkowita” dla 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();
    }
}

Uruchomienie powyższego kodu powoduje błąd w wierszu obj.function(600851475143);. Czemu?

user446654
źródło
1
też nie ma różnicy między „l” i „L”?
user446654
@ user446654: Nie, jest. Ta ostatnia jest bardziej czytelna. Przeczytaj „Java Puzzler”.
Adeel Ansari
@ user446654: ewoluujące myśli @Thilo o możliwym przekroczeniu limitu pamięci Chcę dodać moje 2 monety: wybrałeś naprawdę zły algorytm wyszukiwania wszystkich dzielników liczby, jeśli chcesz operować na tak dużych liczbach, jak w twoim przykładzie. Coś opartego na programowaniu dynamicznym prawdopodobnie działałoby lepiej. Google na to, aby uzyskać dalsze wyniki.
Roman
1
Dodano tag PE, Project Euler # 3
st0le
@ st0le: IMHO pytanie zdecydowanie nie dotyczy oryginalnego rozwiązania problemu, a to, co widzimy, również nie jest rozwiązaniem.
Roman

Odpowiedzi:

200

600851475143nie może być reprezentowany jako 32-bitowa liczba całkowita (typ int). Może być reprezentowany jako 64-bitowa liczba całkowita (typ long). długie literały w Javie kończą się literą „L”:600851475143L

Yuliy
źródło
71

Dołączająca sufiks L: 23423429L.

Domyślnie java interpretuje wszystkie literały liczbowe jako 32-bitowe wartości całkowite. Jeśli chcesz wyraźnie określić, że jest to coś większego niż 32-bitowa liczba całkowita, powinieneś używać sufiksu Ldla długich wartości.

rzymski
źródło
Dla tych, którzy szukają dokładniejszego wyjaśnienia, dlaczego otrzymujesz ten komunikat o błędzie nawet po zmianie typu zmiennej na long, przeczytaj to: stackoverflow.com/a/8924925/293280
Joshua Pinter
29

Musisz użyć długiego literału:

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

Ale spodziewałbym się, że tej funkcji zabraknie pamięci (lub czasu) ...

Thilo
źródło
17
uważa się, że lepszą praktyką ljest 1
pisanie
2
@Bozho: Zgoda. Ale mam doświadczenie w Perlu. Koduję „tylko do zapisu” :-)
Thilo
Użyj „L” zamiast „l”
Kevin V
13

Kompilator java domyślnie próbuje zinterpretować 600851475143 jako stałą wartość typu int. Powoduje to błąd, ponieważ 600851475143 nie może być reprezentowane przez int.

Aby powiedzieć kompilatorowi, że chcesz, aby liczba była interpretowana tak długo, musisz dodać albo lalbo Lpo niej. Twój numer powinien wtedy wyglądać tak600851475143L .

Ponieważ niektóre czcionki utrudniają odróżnienie od siebie „1” i małych liter „l”, należy zawsze używać dużej litery „L”.

josefx
źródło
6

Potrzebujesz 40 bitów, aby przedstawić literał liczby całkowitej 600851475143. Jednak w Javie maksymalna wartość liczby całkowitej to 2 ^ 31-1 (tj. Liczby całkowite są 32-bitowe, zobacz http://download.oracle.com/javase/1.4.2/docs /api/java/lang/Integer.html ).

To nie ma z tym nic wspólnego function. Zamiast tego spróbuj użyć długiego literału liczby całkowitej (jak sugerowano w innych odpowiedziach).

Andre Holzner
źródło
4

W czasie kompilacji liczba „600851475143” jest reprezentowana jako 32-bitowa liczba całkowita, zamiast tego spróbuj użyć długiego literału na końcu numeru, aby rozwiązać ten problem.

JVM
źródło
3

Oprócz wszystkich innych odpowiedzi, możesz zrobić:

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

na przykład :

obj.function(Long.parseLong("600851475143"));
Anand Undavia
źródło
1

Lub możesz zadeklarować liczbę wejściową jako długą, a następnie pozwól jej wykonać kod 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
źródło