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

в 5:22, , рубрики: большие числа, оперативная память, переменные, Песочница, метки: , ,

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

Пример кода

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. Я не буду расписывать что это такое, а просто дам линки на статьи.

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

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

Массив

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

Автор: danpetruk

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js