Вопрос

Почему этот java-код

long a4 = 1L;
long a3 = 1;
long a2 = 100L * 1024 * 1024 * 1024;
long a1 = 100 * 1024 * 1024 * 1024;
System.out.println(a4);
System.out.println(a3);
System.out.println(a2);
System.out.println(a1);

при запуске выводится

1
1
107374182400
0

вместо ожидаемого

1
1
107374182400
107374182400

результат?

Это было полезно?

Решение 2

107374182400 ровно в 25 раз превышает полный диапазон целого числа (2^32), что означает, что если вы попытаетесь вписать его в целое число, это будет переполнение. Анкет И поскольку он будет соответствовать ровно 25 раз, он в конечном итоге в конечном итоге в 0 (это совпадение, и другие огромные умножения могут в конечном итоге оказаться позитивными или отрицательными). И вы используете целое число до такой степени

long a1 = 100 * 1024 * 1024 * 1024;

эквивалентно

int temp = 100 * 1024 * 1024 * 1024;
long a1 = (long)temp;

Если вы положили в выражение одного, он вынужден использовать длинные математики, а не целочисленные математики, которая устраняет проблему

Другие советы

 long a2 = 100L * 1024 * 1024 * 1024;

В этой операции, однако, по крайней мере один операнд long. Анкет Следовательно, операция выполняется с использованием 64-битной точности, и результат численного оператора имеет тип long. Анкет Другой не длинный операнд расширяется до типа long по числовое продвижение и получается, что значение хранится к переменной a2.

 long a1 = 100 * 1024 * 1024 * 1024;

Постоянная экспрессия простого целого числа, результат выражения был рассчитан как тип int. Анкет Вычисленное значение, однако, слишком большое, чтобы вписаться в целое число и, следовательно, переполнено, что привело к 0 и хранится a1 переменная.

РЕДАКТИРОВАТЬ: Как задается в следующем комментарии:

Почему это не отрицательно?

Потому что, пока в целочисленное вычисление Второе вычисление эквивалентно 25 * 2^32 куда ^ имеет значение мощности и 2^32 целочисленное значение есть 0. Анкет Однако, чтобы объяснить, почему это ценность 0: В бинарном:

 100 * 1024 * 1024 * 1024 == 25 * 2^32;

 Integer.MAX_VALUE =  2 ^ 31 -1 = 0 11111111 11111111 11111111 1111111
 Integer.MAX_VALUE + 1 = 2 ^ 31 = 1 00000000 00000000 00000000 0000000 

2 ^ 31 это негативное целое число (-2147483648) как бит знака 1 И, следовательно 2 ^ 32 это просто умножение 2 к 2 ^ 31: Левая смена, и бит знака станет 0 и, следовательно, результат 0.

Проверьте java language specification: 4.2.2: Integer operation Для деталей.

Может быть, выражение справа от a1 сначала рассчитывается как int а позже преобразован в long. Анкет Если это равно 0 как int это останется 0 как long

В соответствии с Документация лексических литералов упоминается, что,

Тип буквального определяется следующим образом:
- Тип целочисленного буквального (§3.10.1), который заканчивается L или L, является длинным (§4.2.1).
- Тип любого другого целочисленного литерала - int (§4.2.1).

Таким образом, ваше выражение, 100 * 1024 * 1024 * 1024 оценивается как int Примитивный тип данных, потому что l или же L не упоминается ни в каком числовом значении. И результат 107374182400 т.е. в бинарном 1 1001 0000 0000 0000 0000 0000 0000 0000 0000 а также int 32-битный так низкий 32-разряд Пример 4.2.2-1. Целочисленные операции который приводит к 0

Также упоминается в той же документации, что, что,

Если целочисленный оператор, отличный от оператора Shift, имеет по крайней мере один операнд длиной типа, то операция выполняется с использованием 64-битной точности, а результат численного оператора имеет длинный тип. Если другой операнд не долгий, сначала расширяется (§5.1.5), чтобы набрать длинные с помощью численного продвижения по службе

Это означает, что любое значение в выражении содержит l или же L тогда все int Значения будут расширены до 64 бит.

РЕДАКТИРОВАТЬ В комментарий также спрашивают

Почему это не отрицательно?

Я думаю это тоже отвечает на приведенный выше вопрос

long a4 = 1L; // нет проблем в этом

long a3 = 1; // Здесь левая сторона примитив считается целым числом, и во время назначения он будет подчиняться долго, так что еще раз результат, как и ожидалось

long a2 = 100L * 1024 * 1024 * 1024; (Здесь вы использовали 100L, чтобы другие были типом, начитываемые к долгом, так что ожидаемый вывод)

long a1 = 100 * 1024 * 1024 * 1024; (Поскольку по умолчанию любая примитивная цифра рассматривается как int в Java, она будет рассматривать это как целочисленное умножение, так что она выходит из диапазона и приводит к 0)

Вот что вы сделали :Вы назначены 100 * 1024 * 1024 * 1024 к длинному типу данных, но вы этого не сказали 100 * 1024 * 1024 * 1024 является длинным значением

По умолчанию компилятор java считает, что это целое число.Поскольку integer не может содержать такого большого значения, он покажет неверный результат.Надеюсь , это поможет !

Причина целое число переполнений
как вывод 100 * 1024 * 1024 * 1024; целое число (это целое число (int) нет long

И в long a2 = 100L * 1024 * 1024 * 1024; Вы указываете, что одно из значений long (здесь 100L) и умножение с этим значением приводит к long значение, которое правильно хранится в a2

В Java, если у вас есть int * int, он будет вычислять выход как int. Это дает результат только как длинный, если вы делаете Int * Long. В вашем случае, 100 * 1024 * 1024 * 1024 имеет результат, который переполняет Int.

Таким образом, добавление «L» делает операнд долгим, а вычисление сохраняет значения долго. И, конечно, не происходит переполнения, и правильный результат может быть выведен (т.е. A2).

Номер 3 работал, потому что вы указали длинный тип, который составляет 100 л. Вот почему это длинное умножение и может быть сохранено. С другой стороны, номер 4-это целочисленное умножение с максимальным значением 2^32-1 Вот почему вы получили переполнение, и появился нулевой ценник по умолчанию.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top