- PVSM.RU - https://www.pvsm.ru -

Почему при увеличении переменной она вдруг уходит в минус и как от этого защититься

Посвящается новичкам, которые недоумевают, почему значение в переменной в какой-то момент уходит в минус

Пример кода

public class Main {

static int IWantMore;

public static void main(String[] args) {

    while (true) {
        IWantMore++;
        System.out.println(IWantMore);
        if (IWantMore == 0) break;
    }
}

}

С каждым новом заходом он прибавляет к IWantMore. Казалось бы, что цикл не остановиться, так как к моменту первой проверки if -ом значение будет 1, но это не так…

В консоли мы увидим следующие:

1
2
3

2147483646
2147483647
-2147483647
-2147483646

-3
-2
-1
0

Чем примечательно число 2147483647? Да это же максимальное значение int! Переведем это число в двоичный вид:

0 1111111111111111111111111111111 (1 + 31 знак — первый отвечает за знак перед числом: 0 — плюс, 1 -минус,, последующие за само число )

32 знака в оперативной памяти — именно столько выделяется под int

При прибавлении к 2147483647 единицы мы по идее должны получить следующие:

010000000000000000000000000000000 (33 знака)

Однако на int стоит жёсткое ограничение — 32 знака. Поэтому первый знак автоматически убирается и получается:

10000000000000000000000000000000 (32 знака)

Что эквивалентно -2147483647!

Как защититься?

Главный способ

Используйте long вместо int. В 99.9% случаях его хватает

Если long -а не хватает

java.Math.BigInteger

Если вы используете java, то вам повезло. Есть готовое решение — BigInteger. Я не буду расписывать что это такое, а просто дам линки [1] на [2] статьи [3].

Значение деления

Есть число 9999999999999999999999999. Поделим его на макс. значение int (на long тоже можно, но не нужно) и запишем этот результат в переменную double. Такое число легко восстановить.

Массив

Записывать число в массив из нескольких long -ов, сложив которые будет получаться это число //Не очень хороший способ, т.к. ест много оперативной памяти

Автор: danpetruk

Источник [4]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/peremenny-e/32515

Ссылки в тексте:

[1] линки: http://www.javaprobooks.ru/java-%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5/%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%B0-%D1%81-%D0%B1%D0%BE%D0%BB%D1%8C%D1%88%D0%B8%D0%BC%D0%B8-%D1%87%D0%B8%D1%81%D0%BB%D0%B0%D0%BC%D0%B8-%D0%B2-java.html

[2] на: http://doc.java.sun.com/DocWeb/api/java.math.BigInteger

[3] статьи: http://spec-zone.ru/RU/Java/Docs/7/api/java/math/BigInteger.html

[4] Источник: http://habrahabr.ru/post/177245/