Tại sao n đang thành dương sao đó chuyển thành âm với phép toán `n<<=1`?

Đây là bài: “chuyển từ thập phân sang nhị phân”. Với đoạn code dưới, n sẽ chuyển từ số dương thành số âm.

#include <stdio.h>

int main()
{
    int n = 2;
    for (int i = 0, temp = (sizeof(n) * 8); i < temp; i++, n <<= 1)
        if (n >= 0)
            printf("0");
        else
            printf("1");
    printf("\n");
    return 0;
}

Kết quả chương trình sẽ trả ra

00000000000000000000000000000010

Cho em hỏi tại sao n đang thành dương sao đó chyển thành âm. Cái này có phải do miền giá trị k ạ?
n từ âm chuyển thành dương thì e lại k biết.

Để đơn giản hơn ta dùng kiểu char8 bit.

  • Lúc Đầu giả sử các bit đang có là abcdefgh

Khi dịch trái 1 bit các bit thừa bị cắt đi và thêm 1 bit 0 vào sau
Vòng lặp for diễn ra như sau:

#i *signed bit
 
#0 abcdefgh
#1 bcdefgh0
#2 cdefgh00
#3 defgh000
#4 efgh0000
#5 fgh00000
#6 gh000000
#7 h0000000

Kiểu intchar có bit cao nhất bit đầu tiên chứa dấu của số đó:

Như vậy bít cao nhất sẽ theo thứ tự các bit đầu tiên là: abcdefgh

4 Likes

4 Likes

Lỗi này có tên là Integer overflow (tràn số nguyên). Cụ thể như sau:
Vòng lặp của bạn sẽ lặp 32 lần (0 -> 31). Như vậy đoạn lệnh trên tương đương trên sẽ tương đương với 2^32 = 4.294.967.296, gtrị này lớn hơn khả năng chứa của kiểu int, giới hạn của kiểu int là [-2.147.483.648…2.147.483.647], lúc này biến n sẽ bị tràn và bị quay về gtrị âm dẫn đến kết quả như trên.

3 Likes

Nhưng nó lại từ kết quả âm trở về giá trị dương song lại tiếp tục bạn à

Như mình đã nói. Ở đây, khi nó lặp đến vòng:
Lần thứ 29: n = 1.073.741.824
Lần thứ 30: n = -2.147.483.648 *Chú ý lần này: Nếu ko bị tràn thì gtrị thực của nó là là 2.147.483.648 nhưng vì bị tràn quá giới hạn của nó là 2.147.483.647 nên dẫn đến nó sẽ tràn sang bị quay vòng về -2.147.483.648.
Lần thứ 31: Tương tự câu tl trên nhưng nó ngược lại. Lúc này sau khi nhân thêm với 2, gtrị vượt qua kích thước 4 bytes và các bit của số này lúc này là 100…00, mà kích thước của n là 4 bytes nên nó chỉ nhận đủ 4 bytes dẫn đến n chỉ nhận những số 0 phía sau của số vừa nhân kia, nghĩa là lúc này n = 0. Do điều kiện là n >= 0 sẽ in ra 0 nên kết quả sẽ hiển thị như bạn paste ở trên.

4 Likes

Cảm ơn bạn vì những chưa sẻ rất bổ ích đây. Nhưng mình vẫn chưa hiểu chỗ này mong bạn giải thích hô t
Nếu thay n=166 thì khi
i=23: n= 1,392,508,928
i=24: n= -1,509,949,440
i=25: n= 1,275,068,416

Theo như cách bạn nói thì mình vẫn k hiểu là n đang âm nếu nhân 2 vào thì vượt quá giới hạn kiểu int
nhưng n lại ra số dương là sao?

(post withdrawn by author, will be automatically deleted in 24 hours unless flagged)

2 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?