programing

i = i + i가 0인 이유는 무엇입니까?

luckcodes 2022. 9. 12. 18:31

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 + 4syslog.

그 가 요?i.0

이것에 대해 자세히 설명해 줄 수 있는 사람이 있다면 좋을 것 같습니다.

변경합니다.int로로 합니다.long예상대로 숫자를 인쇄하고 있는 것 같습니다.최대 32비트 값에 도달하는 속도에 놀랐습니다!

서론

문제는 정수 오버플로입니다.오버플로우가 발생하면 최소값으로 돌아가 거기서부터 계속됩니다.언더플로우가 발생하면 최대값으로 되돌아가 거기에서 계속됩니다.아래 이미지는 주행 기록계입니다.오버플로우를 설명할 때 사용합니다.기계적인 오버플로이지만 여전히 좋은 예다.

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★」max digit = 9하면 '최대값을 초과한다'는 의미입니다9 + 1 "", "", "", "", ""를 나타냅니다0단, 로 변경할 수 상위 숫자는 없습니다.1zero'이렇게 하다'는 말이죠.

여기에 이미지 설명 입력 여기에 이미지 설명 입력

타입 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

정수 오버플로가 "뒤집기"인 이유

원본 PDF

이 문제는 정수 오버플로가 원인입니다.

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
...

의 .int2147483648(=231)입니다.0 ~ 2147483647 범위의 모든 10진 리터럴은 int 리터럴이 표시될 수 있지만 리터럴 2147483648은 단항 부정 연산자의 피연산자로만 표시될 수 있습니다.

정수 덧셈이 오버플로우하면 그 결과는 충분히 큰 2'-완성 형식으로 표현되는 수학 합계의 하위 비트가 됩니다.오버플로가 발생하면 결과의 부호는 두 피연산자 값의 수학적 합계의 부호와 같지 않습니다.

언급URL : https://stackoverflow.com/questions/24173463/why-does-i-i-i-give-me-0