Повідомлення про помилку "Ціле число завелике" для 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();
    }
}

При запуску наведеного вище коду він видає помилку на рядку obj.function(600851475143);. Чому?


1
також немає різниці між "l" і "L"?
user446654

@ user446654: Ні, є. Останнє є більш читабельним. Прочитайте "Java Puzzler" для цього.
Adeel Ansari

@ user446654: еволюціонуючі думки @Thilo про можливе перевищення ліміту пам'яті. Я хочу додати свої 2 монети: ви вибрали справді дуже невдалий алгоритм пошуку всіх дільників числа, якщо ви хочете працювати з такими великими числами, як у вашому прикладі. Щось, засноване на динамічному програмуванні, могло б працювати краще. Google про це для подальших результатів.
Роман

1
Додано тег PE, Project Euler # 3
st0le

@ st0le: IMHO питання, безумовно, не стосується оригінального вирішення проблеми, і те, що ми бачимо, також не є рішенням.
Роман

Відповіді:


199

600851475143не може бути представлений як 32-бітове ціле число (тип int). Він може бути представлений як 64-розрядне ціле число (тип long). довгі літерали в Java закінчуються на "L":600851475143L


71

Append суфікс L: 23423429L.

За замовчуванням java інтерпретує всі цифрові літерали як 32-розрядні цілі значення. Якщо ви хочете чітко вказати, що це щось більше, ніж 32-бітове ціле число, вам слід використовувати суфікс Lдля довгих значень.


Для тих, хто шукає більш детального пояснення, чому ви отримуєте це повідомлення про помилку навіть після того, як змінили тип змінної на long, прочитайте це: stackoverflow.com/a/8924925/293280
Джошуа Пінтер,

29

Вам потрібно використовувати довгий літерал:

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

Але я би очікував, що у цієї функції закінчиться пам'ять (або час) ...


17
вважається кращою практикою робити lверхній регістр, щоб його було легко відрізнити1
Божо

2
@Bozho: Погодився. Але я маю досвід Perl. Я кодую "тільки для запису" :-)
Тіло,

Використовуйте "L" замість "l"
Кевін V,

13

Компілятор Java намагається інтерпретувати 600851475143 як постійне значення типу int за замовчуванням. Це спричиняє помилку, оскільки 600851475143 неможливо представити за допомогою int.

Щоб сказати компілятору, що ви хочете, щоб число інтерпретувалось як довго, вам потрібно додати lабо Lпісля нього, або після нього. Тоді ваш номер повинен виглядати так 600851475143L.

Оскільки деякі шрифти ускладнюють розрізнення "1" та нижнього регістру "l" один від одного, завжди слід використовувати великі регістри "L".


6

Вам потрібно 40 бітів для представлення цілочислового літералу 600851475143. У Java максимальне ціле число дорівнює 2 ^ 31-1, однак (тобто цілі числа 32 бітні, див. Http://download.oracle.com/javase/1.4.2/docs /api/java/lang/Integer.html ).

Це не має нічого спільного function. Спробуйте замість цього використовувати довгий цілочисельний літерал (як пропонується в інших відповідях).


4

Під час компіляції число "600851475143" представляється у 32-розрядному цілому числі, спробуйте замість цього довгий літерал у кінці вашого номера, щоб перейти від цієї проблеми.


3

Окрім усіх інших відповідей, ви можете:

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

наприклад :

obj.function(Long.parseLong("600851475143"));

1

Або ви можете оголосити введений номер як довгий, а потім дозволити йому виконувати кодове танго: 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;
        }
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.