1

Я работаю над упражнениями из книги «Java SE 8 для действительно нетерпимого» Кей С. Хорстманна. Одно из упражнений, основанных на улучшениях в Number классов спрашивает:Java 8 Неподписанное целочисленное добавление и переполнение потенциала

Напишите программу, которая добавляет, вычитает, делит, и сравнивает число между 0 и 2 - 1, используя int значения и без знака операции. Показать почему divideUnsigned и remainderUnsigned необходимо.

Проблема в том, что если вы добавите 2 беззнаковых ints, сумма может переполнить целочисленный предел. Я не вижу способа предотвратить это, не используя долгое время для хранения суммы и проверки, если она больше Integer.MAX_VALUE. Можно ли это сделать только с помощью ints?

ответ

3

Two's complement Используется для целочисленных значений, имеет чистое свойство, которое для добавления и вычитания не имеет значения, интерпретируете ли вы значения как подписанные, так и без знака.

Таким образом, даже на уровне ЦП нет четких инструкций по добавлению/вычитанию подписанных или неподписанных чисел. Все дело в толковании.

Поэтому, когда вы добавляете или вычитаете два неподписанных числа с использованием подписанного типа int, результат может переполняться в диапазоне int. Но при печати отрицательного числа Integer.toUnsignedString результатом будет правильное значение без знака, если предположить, что операция не переполнилась в целых значениях без знака.

Вот почему класс java.lang.Integer обеспечивает только в случае необходимости специальные неподписанные операции, то есть для сравнения двух значений без знака, для деления и остатка и преобразования от и до String (и к long, в то время как тип-бросок от long к int является уже достаточно для другого направления).

+0

Спасибо за ваш ответ. Я не уверен, что вопрос только с печатью. Если значение переполнения возвращается и будет использоваться в какой-либо другой операции, оно будет неверным. «Точные» операции, которые были введены в Java 8, [intValueExact] (http://docs.oracle.com/javase/8/docs/api/java/math/BigInteger.html#intValueExact--), вызывают исключения из таких случаях. –

+1

Поскольку упражнение предусматривает использование 'int' для вычислений, нет никакого способа обойти это. Конечно, вы можете определить API своих вычислений безопасным способом, то есть вы можете использовать ['Integer.toUnsignedLong'] (http://docs.oracle.com/javase/8/docs/api/java/lang/ Integer.html # toUnsignedLong-int-), чтобы вернуть значение (которое вы рассчитали с помощью 'int') в форме, которая не может быть неверно истолкована. Конечно, это было бы так, если бы вы вернули результат как «String», используя ['toUnsignedString'] (http://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html#toUnsignedString -int-) "расчет" '! =' "возвращаемый тип" – Holger

+0

Я надеялся, что есть нечто большее, чем это. Если вы прочитаете вопрос, в нем говорится «использование значений« int »и неподписанных операций». Если кажется, что тривиальным является создание метода, который использует оператор '+' для добавления 2 int. Упражнение не добавляет никакой ценности, если мы не упускаем что-то. –

1

Для получения неподписанного int вам необходимо использовать функции Integer.parseUnsignedInt() или выполнить ручной расчет. Помните, что Java фактически не имеет целых чисел без знака, Java8 просто предоставляет возможность обрабатывать int как unsigned, чтобы обеспечить больший диапазон значений положительного числа.

Согласно Java 8 Doc for the Integer class,

Целое число без знака отображает значения, как правило, связанные с отрицательными чисел до положительных чисел больше, чем MAX_VALUE

Таким образом, преобразование между неподписанных INT и подписанную один что если число больше или равно нулю И меньше или равно Integer.MAX_VALUE, оно остается неизменным. Если он больше, чем Integer.MAX_VALUE, но все еще находится в пределах диапазона без знака, то для его сохранения в файле int вам нужно добавить к нему 2^31, что преобразует его в правильное значение из-за того, что переполнение добавления определяется как Операция. Переполнение и недополнение в дополнение к двоичным примитивам, таким как int, просто заставляет счетчик сбросить и продолжить подсчет.

int min = Integer.MIN_VALUE;   // -2147483648 
int max = Integer.MAX_VALUE;   // 2147483647 
int overByOne = Integer.MAX_VALUE + 1; // -2147483648 : same as Integer.MIN_VALUE 
int underByOne = Integer.MIN_VALUE - 1; // 2147483647 : same as Integer.MAX_VALUE 

Они осуществляют только прошу вас, чтобы посмотреть на класс Integer и проверить различные (новые в Java8) методы для неподписанных операций. Java не имеет беззнаковых целочисленных примитивов, но значение int можно рассматривать как unsigned для целей некоторых новых методов в классе Integer.

 Смежные вопросы

  • Нет связанных вопросов^_^