i = i + i가 0인 이유는 무엇입니까?
간단한 프로그램이 있습니다.
public class Mathz {
static int i = 1;
public static void main(String[] args) {
while (true){
i = i + i;
System.out.println(i);
}
}
}
은 '아예'뿐입니다.0
★★★★★★에i
첫 는 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★i = 1 + 1
그에 , , 음음음음음 , ,i = 2 + 2
그에 , , 음음음음음 , ,i = 4 + 4
syslog.
그 가 요?i
.0
이것에 대해 자세히 설명해 줄 수 있는 사람이 있다면 좋을 것 같습니다.
변경합니다.int
로로 합니다.long
예상대로 숫자를 인쇄하고 있는 것 같습니다.최대 32비트 값에 도달하는 속도에 놀랐습니다!
서론
문제는 정수 오버플로입니다.오버플로우가 발생하면 최소값으로 돌아가 거기서부터 계속됩니다.언더플로우가 발생하면 최대값으로 되돌아가 거기에서 계속됩니다.아래 이미지는 주행 기록계입니다.오버플로우를 설명할 때 사용합니다.기계적인 오버플로이지만 여전히 좋은 예다.
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★」max digit = 9
하면 '최대값을 초과한다'는 의미입니다9 + 1
"", "", "", "", ""를 나타냅니다0
단, 로 변경할 수 상위 숫자는 없습니다.1
zero
'이렇게 하다'는 말이죠.
타입 int의 최대 10진 리터럴은 2147483647(2-131)입니다.0 ~ 2147483647 범위의 모든 10진 리터럴은 int 리터럴이 표시될 수 있지만 리터럴 2147483648은 단항 부정 연산자의 피연산자로만 표시될 수 있습니다.
정수 덧셈이 오버플로우하면 그 결과는 충분히 큰 2'-완성 형식으로 표현되는 수학 합계의 하위 비트가 됩니다.오버플로가 발생하면 결과의 부호는 두 피연산자 값의 수학적 합계의 부호와 같지 않습니다.
thus따는2147483647 + 1
-2147483648
.이런 이유로int i=2147483647 + 1
하면 안 요, 안 돼요, 안 돼요.2147483648
그리고 '항상 0이 출력된다'고 합니다.http://ideone.com/WHrQIW 이므로 그렇지 않습니다.다음 8개의 숫자는 피벗과 오버플로우의 포인트를 나타내고 있습니다.그 후, 0 의 인쇄가 개시됩니다.또한 오늘날의 기계는 매우 빠르기 때문에 계산 속도가 매우 빠릅니다.
268435456
536870912
1073741824
-2147483648
0
0
0
0
정수 오버플로가 "뒤집기"인 이유
이 문제는 정수 오버플로가 원인입니다.
32비트 2완성 산술:
i
는 실제로는 2의 거듭제곱으로 시작하지만 2가 되면30 오버플로 동작이 시작됩니다.
230 + 230 = -231
-231 + -231 = 0
의 경우...인int
산술은 기본적으로 산술 모드 2^32이기 때문입니다.
아니요, 0만 출력하지 않습니다.
이걸로 바꾸면 무슨 일이 일어나는지 알 수 있을 거예요.
int k = 50;
while (true){
i = i + i;
System.out.println(i);
k--;
if (k<0) break;
}
일어나는 일을 오버플로라고 합니다.
static int i = 1;
public static void main(String[] args) throws InterruptedException {
while (true){
i = i + i;
System.out.println(i);
Thread.sleep(100);
}
}
출력:
2
4
8
16
32
64
...
1073741824
-2147483648
0
0
when sum > Integer.MAX_INT then assign i = 0;
저는 평판이 좋지 않기 때문에, 같은 프로그램의 출력 이미지를 C에 제어 출력으로 투고할 수 없기 때문에, 실제로 32 회 인쇄하고 나서, 오버플로우 i=44041824 + 1073741824가 -2147483648로 변경되어, 한층 더 추가된 것이 int의 범위를 벗어나 로 바뀝니다.
#include<stdio.h>
#include<conio.h>
int main()
{
static int i = 1;
while (true){
i = i + i;
printf("\n%d",i);
_getch();
}
return 0;
}
「」의 값i
는 일정한 양의 이진수를 사용하여 메모리에 저장됩니다.사용 가능한 숫자보다 많은 숫자가 필요한 경우 가장 낮은 숫자만 저장됩니다(가장 높은 숫자는 손실됩니다).
" " " i
는 곱하는 것과 .i
에서는 숫자에 로 각 것도으로 할 수 있다.각 숫자를 왼쪽으로 슬라이드시켜 오른쪽에 0을 붙이면 10을 곱하는 것과 마찬가지로 2진법에서도 2를 곱하는 것이 가능하다.그러면 오른쪽에 한 자리 숫자가 추가되므로 왼쪽에서 한 자리 숫자가 손실됩니다.
로 1을 . 에잇i
(예:),
- 이 0이 됩니다.
00000001
- 반복하면 1회 반복하면 1회 값이 .
00000010
- 하면 2번 하면 2번 됩니다.
00000100
0이 아닌 마지막 단계가 될 때까지
- 은 7회 반복됩니다.
10000000
- 은 8회 반복됩니다.
00000000
숫자를 저장하기 위해 할당된 이진수나 시작 값이 무엇이든 간에 결국 왼쪽으로 밀리면 모든 숫자가 손실됩니다.이 시점 이후 숫자를 계속 두 배로 늘려도 숫자는 변경되지 않습니다. 숫자는 여전히 모두 0으로 표시됩니다.
맞습니다만, 31회 반복하면 1073741824 + 1073741824 가 올바르게 계산되지 않고(오버플로우), 그 후에는 0 만 출력됩니다.
BigInteger를 사용하도록 리팩터링할 수 있으므로 무한 루프가 올바르게 작동합니다.
public class Mathz {
static BigInteger i = new BigInteger("1");
public static void main(String[] args) {
while (true){
i = i.add(i);
System.out.println(i);
}
}
}
이러한 경우의 디버깅에는 루프 내의 반복 횟수를 줄이는 것이 좋습니다.사용자 이름 대신 사용while(true)
:
for(int r = 0; r<100; r++)
그런 다음 2부터 시작하여 오버플로를 일으킬 때까지 값이 두 배로 증가하는 것을 볼 수 있습니다.
8비트의 숫자를 일러스트레이션에 사용합니다.짧은 공간에서 상세하게 설명할 수 있기 때문입니다.16진수는 0x로 시작하고 이진수는 0b로 시작합니다.
8비트 부호 없는 정수의 최대값은 255(0xFF 또는 0b1111)입니다.1을 더하면 보통 256(0x100 또는 0b100000000)이 됩니다.단, 비트(9)가 너무 많으므로 첫 번째 부품은 폐기되고 0x(1)0000000000은 사실상 폐기됩니다(0x(1)000000은 폐기되지만 1은 폐기됩니다).
따라서 프로그램이 실행되면 다음과 같은 이점이 있습니다.
1 = 0x01 = 0b1
2 = 0x02 = 0b10
4 = 0x04 = 0b100
8 = 0x08 = 0b1000
16 = 0x10 = 0b10000
32 = 0x20 = 0b100000
64 = 0x40 = 0b1000000
128 = 0x80 = 0b10000000
256 = 0x00 = 0b00000000 (wraps to 0)
0 + 0 = 0 = 0x00 = 0b00000000
0 + 0 = 0 = 0x00 = 0b00000000
0 + 0 = 0 = 0x00 = 0b00000000
...
의 .int
는 2147483648(=231)입니다.0 ~ 2147483647 범위의 모든 10진 리터럴은 int 리터럴이 표시될 수 있지만 리터럴 2147483648은 단항 부정 연산자의 피연산자로만 표시될 수 있습니다.
정수 덧셈이 오버플로우하면 그 결과는 충분히 큰 2'-완성 형식으로 표현되는 수학 합계의 하위 비트가 됩니다.오버플로가 발생하면 결과의 부호는 두 피연산자 값의 수학적 합계의 부호와 같지 않습니다.
언급URL : https://stackoverflow.com/questions/24173463/why-does-i-i-i-give-me-0
'programing' 카테고리의 다른 글
MariaDB/MySQL을 사용하여 Peeee에서 FLOAT 열 정밀도 지정 (0) | 2022.09.12 |
---|---|
MySQL에서의 VARCHAR과 TEXT의 차이점 (0) | 2022.09.12 |
Java용 SQL 파서 라이브러리 (0) | 2022.09.12 |
Nuxt Auth Module을 사용하여 Vuex에서 사용자를 다시 설정하는 방법 (0) | 2022.08.15 |
Java 예외가 검출되지 않았습니까? (0) | 2022.08.15 |