문제

이 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 먼저 An으로 계산됩니다 int 그리고 나중에 변환되었습니다 long. 동일하다면 0 로서 int 머물 것입니다 0 A로 long

에 따라 어휘 리터럴의 문서화 그것은 언급되어 있습니다.

문자의 유형은 다음과 같이 결정됩니다.
-L 또는 L로 끝나는 정수 문자 문자 (§3.10.1)의 유형은 길다 (§4.2.1).
- 다른 정수 문자의 유형은 int (§4.2.1)입니다.

따라서 당신의 표현, 100 * 1024 * 1024 * 1024 AS로 평가됩니다 int 원시 데이터 유형 때문에 l 또는 L 숫자 값으로 언급되지 않았습니다. 그리고 결과는입니다 107374182400 즉, 바이너리에 있습니다 1 1001 0000 0000 0000 0000 0000 0000 0000 0000 그리고 int 32 비트이므로 32 비트가 낮습니다. 예 4.2.2-1. 정수 작업 그 결과 0

또한 같은 문서에서 언급되어 있습니다.

시프트 연산자 이외의 정수 연산자가 하나 이상의 유형의 오페라가 길이가 길어지면 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; (기본적으로 모든 원시 숫자는 Java에서 int로 간주되므로 이것을 정수 곱셈으로 간주하여 범위를 벗어나 0이됩니다.

당신이 한 일은 다음과 같습니다. 당신은 할당했습니다 100 * 1024 * 1024 * 1024긴 데이터 유형에 대해서도 100 * 1024 * 1024 * 1024 긴 가치입니다

기본적으로 Java 컴파일러는 정수라고 생각합니다. 정수는 그다지 많은 가치를 유지할 수 없으므로 잘못된 결과를 보일 것입니다. 도움이되기를 바랍니다!

이유입니다 정수 오버플로
출력으로 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은 100L 인 긴 유형을 지정했기 때문에 작동했습니다. 그렇기 때문에 곱셈이 길고 저장 될 수 있습니다. 반면에 4 번은 최대 값 2^32-1의 정수 곱셈이 있습니다. 그래서 당신은 오버플로를 얻었고 기본값 값이 나타났습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top