#java #integer-overflow
#java #целое число-переполнение
Вопрос:
Мне трудно понять поведение java в следующем сценарии. Например, у меня есть метод multiply, который просто умножает два значения int и выводит результат на экран.
private static void multiply() {
int firstValue = Integer.MAX_VALUE;
int secondValue = 2; //double secondValue=2
double result = firstValue * secondValue;
System.out.println("Result is: " result);
}
и из-за того, что переполнение целых чисел, результат равен -2. Однако здесь результат вычисления присваивается двойному, который принимает гораздо большее значение, чем умножение FirstValue и secondValue.
Мои вопросы к этой проблеме;
1- Почему происходит переполнение целых чисел, хотя результат присваивается двойному?
2- Когда я меняю тип secondValue на double (упоминается в комментарии), результат верен. Почему Java ведет себя по-разному, когда тип одного из множителей изменяется на double?
Комментарии:
1. Вычисление производится как целое число, и результат преобразуется в double только после вычисления. Итак, есть момент, когда ваш int в два раза больше MAX_VALUE, что даст ваш результат
2. Умножение включает только целые числа, поэтому оно выполняется как целочисленное умножение. Только после этого результат преобразуется в double, но в это время уже слишком поздно. Приведите одно из значений при умножении.
Ответ №1:
Java не поддерживается target type casting
.
private static void multiply() {
int firstValue = Integer.MAX_VALUE;
int secondValue = 2;
double one = 1.0;
double result = one * firstValue * secondValue;
System.out.println("Result is: " result);
}
Target Type casting
означает приведение значения результата к типу переменной, которой оно должно быть присвоено.
Таким образом, он не знает, что результат должен быть присвоен double
переменной. В этом случае int
это самый большой тип данных, поэтому выражение вычисляется в int
типе данных.
если вы умножаете его на double
единицу, выражение вычисляется в double
type и ответ правильный.
Комментарии:
1. Однако в вашем примере, когда переменная one находится в конце (двойной результат = FirstValue * secondValue * one), переполнение целых чисел все равно происходит. Я думаю, java смотрит порядок переменной в вычислении или?
2. Это из-за порядка операций.
Ответ №2:
Результатом умножения двух int
s является значение an int
, которое может переполняться или не переполняться, в зависимости от значения умножения. Как только этот результат получен, он только затем повышается до a double
, после того, как могло произойти переполнение.
Если один из операндов является a double
, результатом умножения будет a double
, что допускает гораздо больший диапазон, чем an int
.
Комментарии:
1. Однако, если вы посмотрите на пример Ankit. Когда я помещаю переменную one , которая равна double, в конце вычисления, переполнение целых чисел все равно происходит, даже если один из множителей равен double.
2. @AdInfinitum Это потому, что порядок операций. Два целых числа сначала умножаются на переполнение, затем умножаются на удвоение и повышаются.
3. @AndrewL. Спасибо. Вы правы. После вашего комментария я помещаю последние два множителя (secondValue и one ) в круглые скобки, и это дает правильный ответ.
Ответ №3:
это ожидаемо, потому что, когда вы умножаете 2 целых числа, результатом является только целое число. Это работает с другим способом, когда вы используете double в качестве одного из полей, результат будет рассматриваться как двойное значение. тип данных получателей здесь не имеет значения