Что происходит, когда вы увеличиваете целое число сверх его максимального значения?
В Java что происходит, когда вы увеличиваете int (или byte/short/long) сверх его максимального значения? Оборачивается ли оно до максимального отрицательного значения?
AtomicInteger.getAndIncrement() также ведет себя так же?
6 ответов
Из раздела Спецификации языка Java о целочисленных операциях:
Встроенные целочисленные операторы никоим образом не указывают на переполнение или потерю значения.
Результаты определяются языком и не зависят от версии JVM: Integer.MAX_VALUE + 1 == Integer.MIN_VALUE
а также Integer.MIN_VALUE - 1 == Integer.MAX_VALUE
, То же самое касается других целочисленных типов.
Целочисленные атомные объекты (AtomicInteger
, AtomicLong
и т. д.) внутренне используют обычные целочисленные операторы, поэтому getAndDecrement()
и т.д. ведут себя так же.
Если вы делаете что-то вроде этого:
int x = 2147483647;
x++;
Если вы теперь распечатаете x, это будет значение -2147483648
Как говорит jterrace, среда выполнения Java "обернет" результат в Integer.MIN_VALUE, равный -2147483648.
Но это математически неверно! Правильный математический ответ - 2147483648. Но значение int не может иметь значение 2147483648. Границы int - от -2147483648 до 2147483647.
Так почему же Java не создает исключение? Хороший вопрос! Объект Array будет.
Но авторы языка знают область применения своих примитивных типов, поэтому они используют технику "обертывания", чтобы избежать дорогостоящего исключения.
Вы, как разработчик, должны проверить границы этих типов. Простой тест для увеличения будет
if(x++ == Integer.MIN_VALUE)
//boundary exceeded
Простой тест на уменьшение будет
if(x-- == Integer.MAX_VALUE)
//boundary exceeded
Полный тест для обоих будет
if(x++ == Integer.MIN_VALUE || x-- == Integer.MAX_VALUE)
//boundary exceeded
Что происходит, если в самый дальний правый бит добавляется дополнительный бит, а порядок уменьшается как отрицательный знак типа int ... Обратите внимание, что происходит после 'int_32';
int _0 = 0b0000000000000000000000000000000;
int _1 = 0b0000000000000000000000000000001;
int _2 = 0b0000000000000000000000000000010;
int _3 = 0b0000000000000000000000000000100;
int _4 = 0b0000000000000000000000000001000;
int _5 = 0b0000000000000000000000000010000;
int _6 = 0b0000000000000000000000000100000;
int _7 = 0b0000000000000000000000001000000;
int _8 = 0b0000000000000000000000010000000;
int _9 = 0b0000000000000000000000100000000;
int _10 = 0b0000000000000000000001000000000;
int _11 = 0b0000000000000000000010000000000;
int _12 = 0b0000000000000000000100000000000;
int _13 = 0b0000000000000000001000000000000;
int _14 = 0b0000000000000000010000000000000;
int _15 = 0b0000000000000000100000000000000;
int _16 = 0b0000000000000001000000000000000;
int _17 = 0b0000000000000010000000000000000;
int _18 = 0b0000000000000100000000000000000;
int _19 = 0b0000000000001000000000000000000;
int _20 = 0b0000000000010000000000000000000;
int _21 = 0b0000000000100000000000000000000;
int _22 = 0b0000000001000000000000000000000;
int _23 = 0b0000000010000000000000000000000;
int _24 = 0b0000000100000000000000000000000;
int _25 = 0b0000001000000000000000000000000;
int _26 = 0b0000010000000000000000000000000;
int _27 = 0b0000100000000000000000000000000;
int _28 = 0b0001000000000000000000000000000;
int _29 = 0b0010000000000000000000000000000;
int _30 = 0b0100000000000000000000000000000;
int _31 = 0b1000000000000000000000000000000;
int _32 = 0b1111111111111111111111111111111;
int _XX = 0b10000000000000000000000000000000; // numeric overflow.
int _33 = 0b10000000000000000000000000000001;
int _34 = 0b11000000000000000000000000000000;
int _35 = 0b11100000000000000000000000000000;
int _36 = 0b11110000000000000000000000000000;
int _37 = 0b11111000000000000000000000000000;
int _38 = 0b11111100000000000000000000000000;
int _39 = 0b11111110000000000000000000000000;
int _40 = 0b11111111000000000000000000000000;
int _41 = 0b11111111100000000000000000000000;
int _42 = 0b11111111110000000000000000000000;
int _43 = 0b11111111111000000000000000000000;
int _44 = 0b11111111111100000000000000000000;
int _45 = 0b11111111111110000000000000000000;
int _46 = 0b11111111111111000000000000000000;
int _47 = 0b11111111111111100000000000000000;
int _48 = 0b11111111111111110000000000000000;
int _49 = 0b11111111111111111000000000000000;
int _50 = 0b11111111111111111100000000000000;
int _51 = 0b11111111111111111110000000000000;
int _52 = 0b11111111111111111111000000000000;
int _53 = 0b11111111111111111111100000000000;
int _54 = 0b11111111111111111111110000000000;
int _55 = 0b11111111111111111111111000000000;
int _56 = 0b11111111111111111111111100000000;
int _57 = 0b11111111111111111111111110000000;
int _58 = 0b11111111111111111111111111000000;
int _59 = 0b11111111111111111111111111100000;
int _60 = 0b11111111111111111111111111110000;
int _61 = 0b11111111111111111111111111111000;
int _62 = 0b11111111111111111111111111111100;
int _63 = 0b11111111111111111111111111111110;
int _64 = 0b11111111111111111111111111111111;
System.out.println( " _0 = " + _0 );
System.out.println( " _1 = " + _1 );
System.out.println( " _2 = " + _2 );
System.out.println( " _3 = " + _3 );
System.out.println( " _4 = " + _4 );
System.out.println( " _5 = " + _5 );
System.out.println( " _6 = " + _6 );
System.out.println( " _7 = " + _7 );
System.out.println( " _8 = " + _8 );
System.out.println( " _9 = " + _9 );
System.out.println( " _10 = " + _10 );
System.out.println( " _11 = " + _11 );
System.out.println( " _12 = " + _12 );
System.out.println( " _13 = " + _13 );
System.out.println( " _14 = " + _14 );
System.out.println( " _15 = " + _15 );
System.out.println( " _16 = " + _16 );
System.out.println( " _17 = " + _17 );
System.out.println( " _18 = " + _18 );
System.out.println( " _19 = " + _19 );
System.out.println( " _20 = " + _20 );
System.out.println( " _21 = " + _21 );
System.out.println( " _22 = " + _22 );
System.out.println( " _23 = " + _23 );
System.out.println( " _24 = " + _24 );
System.out.println( " _25 = " + _25 );
System.out.println( " _26 = " + _26 );
System.out.println( " _27 = " + _27 );
System.out.println( " _28 = " + _28 );
System.out.println( " _29 = " + _29 );
System.out.println( " _30 = " + _30 );
System.out.println( " _31 = " + _31 );
System.out.println( " _32 = " + _32 );
System.out.println( " _xx = " + _xx ); // -2147483648
System.out.println( " _33 = " + _33 );
System.out.println( " _34 = " + _34 );
System.out.println( " _35 = " + _35 );
System.out.println( " _36 = " + _36 );
System.out.println( " _37 = " + _37 );
System.out.println( " _38 = " + _38 );
System.out.println( " _39 = " + _39 );
System.out.println( " _40 = " + _40 );
System.out.println( " _41 = " + _41 );
System.out.println( " _42 = " + _42 );
System.out.println( " _43 = " + _43 );
System.out.println( " _44 = " + _44 );
System.out.println( " _45 = " + _45 );
System.out.println( " _46 = " + _46 );
System.out.println( " _47 = " + _47 );
System.out.println( " _48 = " + _48 );
System.out.println( " _49 = " + _49 );
System.out.println( " _50 = " + _50 );
System.out.println( " _51 = " + _51 );
System.out.println( " _52 = " + _52 );
System.out.println( " _53 = " + _53 );
System.out.println( " _54 = " + _54 );
System.out.println( " _55 = " + _55 );
System.out.println( " _56 = " + _56 );
System.out.println( " _57 = " + _57 );
System.out.println( " _58 = " + _58 );
System.out.println( " _59 = " + _59 );
System.out.println( " _60 = " + _60 );
System.out.println( " _61 = " + _61 );
System.out.println( " _62 = " + _62 );
System.out.println( " _63 = " + _63 );
System.out.println( " _64 = " + _64 );
Если целочисленное сложение переполняется, то результатом являются младшие биты математической суммы, представленные в некотором достаточно большом формате с двумя дополнениями. Если происходит переполнение, то знак результата не совпадает со знаком математической суммы двух значений операнда.
http://java.sun.com/docs/books/jls/second_edition/html/expressions.doc.html
Я знаю, что это что-то вроде некропоста, но я наткнулся на это и подумал, что должен поделиться тем, что я сделал со своей стороны, всем, кто хочет "решить" или мою попытку решить
package main;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Adder {
public static final int DIGITS = 25;
public static void main(String[] args) throws FileNotFoundException {
Scanner input = new Scanner(new File("/Users/swapnil/IdeaProjects/Sum/src/Sum.txt"));
analyze(input);
}
public static void analyze(Scanner input) {
int lines = 0;
while (input.hasNextLine()) {
String line = input.nextLine();
Scanner tokens = new Scanner(line);
int[] operand = new int[DIGITS];
initAdd(tokens, operand);
while (tokens.hasNext()) {
contAdd(tokens, operand);
}
System.out.print(" = ");
printAsNumber(operand);
System.out.println();
lines++;
}
System.out.println();
System.out.println("Total lines = " + lines);
}
public static int[] getNextOperand(Scanner tokens) {
String number = tokens.next();
int lastDigitIndex = DIGITS - number.length();
int[] nextOp = new int[DIGITS];
for (int i = lastDigitIndex; i < DIGITS; i++) {
nextOp[i] = Character.getNumericValue(number.charAt(i - lastDigitIndex));
}
return nextOp;
}
public static void addColumns(Scanner tokens, int operand[], int nextOp[]) {
for (int i = DIGITS - 1; i >= 0; i--) {
operand[i] += nextOp[i];
if (operand[i] > 9) {
int currentDigit = operand[i] % 10;
operand[i] = currentDigit;
operand[i - 1]++;
}
}
}
public static void initAdd(Scanner tokens, int operand[]) {
int[] nextOp = getNextOperand(tokens);
printAsNumber(nextOp);
addColumns(tokens, operand, nextOp);
}
public static void contAdd(Scanner tokens, int operand[]) {
int[] nextOp = getNextOperand(tokens);
System.out.print(" + ");
printAsNumber(nextOp);
addColumns(tokens, operand, nextOp);
}
public static void printAsNumber(int number[]) {
int lastDigitIndex = DIGITS - 1;
for (int i = 0; i < DIGITS; i++) {
if (number[i] != 0) {
lastDigitIndex = i;
break;
}
}
for (int i = lastDigitIndex; i < DIGITS; i++) {
System.out.print(number[i]);
}
}
}
Это обходной путь, поэтому вы все равно можете продолжать в основном бесконечный. Я рекомендую if(int > nearmax) затем перейти к новому int Пример:
int x = 2000000000;
x++;
int stacker = 0;
if (x > 2000000000)
{
int temp = x;
x = temp - 2000000000
stacker++;
}
тогда вы можете отстегнуть при необходимости тоже...
скажем х = 0
x--;
if (x < 0 && stacker > 0)
{
int temp = x;
x = 2000000000 + temp;//plus because it's negative
stacker--;
}
это дает 2000000000 x 2000000000, и я имею в виду... вы могли бы продолжать делать это так... да...
Конечно, вы можете пойти еще дальше, если хотите использовать отрицательные числа...