Trang 1 trên tổng số 2 12 Cuối cùngCuối cùng
Từ 1 tới 10 trên tổng số 15 kết quả

Đề tài: Một số về bitwise operators

  1. #1
    Ngày gia nhập
    09 2006
    Nơi ở
    /usr/share/.hack@
    Bài viết
    1,433

    Talking Một số về bitwise operators

    Một số chú ý về ' Bitwise Operator '
    ----------------------------------------------------
    Các phép toán trên bit :
    _bitwise AND ( & )
    _bitwise OR ( | )
    _bitwise XOR ( ^ )
    _bitwise NOT ( ~ )
    _left shift ( << )
    _right shift ( >> )

    Tóm tắt một chút :
    1. Bitwise AND ( & )
    Chú ý đây là phép toán chỉ áp dụng trên bit cần phân biệt với &&, đây là so sánh toán tử điều kiện
    Bảng giá trị :
    0 & 0 = 0 : 1 & 0 = 0 : 0 & 1 = 0 : 1 & 1 = 1
    Ví dụ : 01101111 & 11110000 = 01100000
    So sánh AND ( & ) từng bit tương ứng ( cùng vị trí hay vị trí tương ứng trong byte )
    Thêm một ví dụ khác :
    $result = 124 & 99;
    Chuyển sang hệ BIN, nhị phân.
    124D = 01111100B
    99D = 01100011B
    D = Decimal : Hệ thập phân (base-10)
    B = Binary : Hệ nhị phân (base-2)
    So sánh từng vị trí bit trong byte theo AND ( & ) thu được
    $result = 96 ( = 01100000B)

    2.Các toán tử khác OR , XOR , NOT :
    OR ( | ) : Bảng giá trị :
    0 | 0 = 0 : 0 | 1 = 1 : 1 | 0 = 1 : 1 | 1 = 1
    XOR ( ^ ) : Bảng giá trị :
    0 ^ 0 = 0 : 0 ^ 1 = 1 : 1 ^ 0 = 1 : 1 ^ 1 = 0
    NOT ( ~ ) :
    ~1 = 0 : ~0 = 1

    3.Hai phép dịch bit : left-shift và right-shift :
    Ví dụ :
    $result = $x >> 1 ;
    mang ý nghĩa : các bit của $x dịch sang phải 1 bit. <hơi khó hiểu>.
    Cụ thể :
    $result = 99 >> 1 ;
    mang ý nghĩa : các bit của 99 dich sang phải 1 bit.
    Từ từ thực hiện :
    chuyển sang hệ nhị phân (binary) : 99D = 01100011B [X]
    dịch sang phải 1 bit tức là : 00110001 [Y]
    So sánh 2 số tại [X] và [Y] để ý thấy :
    từ [X] sang [Y] : bit cuối cùng biến mất và thêm vào đầu là 0 thay thế bit vị trí đầu tiên.
    Có thể hiểu đơn giản : là xóa bit cuối cùng đi và lấp đầy khoảng trống ( thêm 0 vào đầu bit )
    Kết quả : $result = 49 ( = 00110001B )
    Tổng quát hơn : $result = $x >> n ;
    mang ý nghĩa : dịch các bit của $x sang phải n bit ( = n vị trí ), thay thể các vị trí trống = 0
    Các ví dụ trên dùng số nguyên 8-bit.
    Với các bit lớn hơn 16-bit, 32-bit tương tự bạn chỉ cần thêm 0 cho đủ số bit tương ứng.
    Một điều chắc chắn là : giả sử $x là số nguyên k-bit thì khi $x >> n với n >= k kết quả thu được luôn là 0.

    Chú ý khác :
    1). Để ý ví dụ sau :
    $x = 17 >> 1;
    $y = 16 >> 1;
    So sánh $x và $y ?
    17D = 00010001B;
    16D = 00010000B;
    Ái dà : kết quả thu được $x = $y = 8;
    --> Cái này hay nhỉ

    2). Không nên dịch bit quá lớn, vượt quá giới hạn cho phép.
    Giả sử bạn dùng 16-bit với phép tính : $result = 35000 << 1;
    kết quả tính ra thu được 70000 , nghĩ là thế nhưng thực tế là lỗi
    vì giới hạn 16-bit max = 65536.

    3). Dịch bit và Lũy Thừa cơ số 2 :
    so sánh 2 cái này phát :
    $x = 99 >> 1;
    $y = 99 /2;
    Kết quả : $x = $y = 49 ; bằng nhau
    làm phép tính khác ;
    $x = 99 << 1;
    $y = 99 * 2;
    Kết quả : $x = $y = 198; bằng nhau

    Tóm lại có được quy luật chuyển bit
    _Dịch sang trái n bit với n là số nguyên dương thì tương đương với nhân với 2 lũy thừa n
    _Dịch sang phải n bit với n là số nguyên dương thì tương đương với chia với 2 lũy thừa n

    Thành ra dùng quy tắc chuyển dịch trên nhanh hơn cứ ngồi convert rồi dịch bit
    Kiến thức nho nhỏ, viết lại chia sẻ chút ^_^!

    Written by Pete
    None!

  2. #2
    Ngày gia nhập
    05 2007
    Bài viết
    33

    !!^_^!! Lâu lâu post 1 bài ra trò đấy ,

    _Dịch sang trái n bit với n là số nguyên dương thì tương đương với nhân với 2 lũy thừa n
    _Dịch sang phải n bit với n là số nguyên dương thì tương đương với chia với 2 lũy thừa n
    Đôi khi lối suy nghĩ đơn giản lại giúp ích, lúc học hợp ngữ, tớ cũng ghét ba cái vụ dịch chuyển bit này lắm, nhưng nhờ nghĩ đơn giản như vậy nên ....
    NOTHING GONNA CHANGE MY LOVE FOR C

  3. #3
    Ngày gia nhập
    10 2007
    Bài viết
    3

    Cám ơn bác Xcross87 nhé. Em đang tìm hiểu cái này coi bài của bác thì ko thể chê vào đâu được.

  4. #4
    Ngày gia nhập
    09 2008
    Nơi ở
    Heaven
    Bài viết
    10

    Bạn Xcross nhìn rất ngầu,nhưng cảm ơn bạn nhiều,đọc sách Beginning C tới đoạn Bitwise ko hiểu gì hết.Cám ơn.
    Có thể bạn nói tôi bướng bỉnh.Nhưng tôi cho là mình kiên định.
    http://vanphamvn.blogspot.com

  5. #5
    Ngày gia nhập
    09 2008
    Bài viết
    19

    Đôi lúc dịch bit không mang lại kết quả như mình mong đợi. Mình hay gặp một trường hợp trên VC++ 6, là:
    Code:
    int a = 1;
    a = a << 32;
    ;
    Kết quả của a vẫn là 1, thay vì mình mong đợi là 0.

    Thứ hai nữa là :
    _Dịch sang trái n bit với n là số nguyên dương thì tương đương với nhân với 2 lũy thừa n
    _Dịch sang phải n bit với n là số nguyên dương thì tương đương với chia với 2 lũy thừa n
    Cái này không đúng với số âm bù 2 do tính chất đặc biệt của bit dấu.

  6. #6
    Ngày gia nhập
    09 2006
    Nơi ở
    /usr/share/.hack@
    Bài viết
    1,433

    Mặc định Một số về bitwise operators

    Nói về bitwise là người ta thường nhắc đến số nguyên dương chứ có phải mấy trường hợp của các bác đâu trời -_-;;
    None!

  7. #7
    Ngày gia nhập
    09 2008
    Bài viết
    19

    Trường hợp 1 của tui là nguyên dương đó chớ. Và ứng dụng của tui cũng đòi phải làm vậy đó chớ. (1 << 32 = 1!!!).
    Mới thử lại bên g++, nó cho 1 warning và cũng cho ra 1 << 32 = 1 (nhưng (1 << 16) << 16 thì đúng = 0 ^^).

  8. #8
    Ngày gia nhập
    09 2006
    Nơi ở
    /usr/share/.hack@
    Bài viết
    1,433

    Trích dẫn Nguyên bản được gửi bởi hieusua Xem bài viết
    Trường hợp 1 của tui là nguyên dương đó chớ. Và ứng dụng của tui cũng đòi phải làm vậy đó chớ. (1 << 32 = 1!!!).
    Mới thử lại bên g++, nó cho 1 warning và cũng cho ra 1 << 32 = 1 (nhưng (1 << 16) << 16 thì đúng = 0 ^^).
    Này, tôi không biết cậu giỏi thế nào chứ. Cậu đọc hết từng chữ của bài tôi viết chưa ???
    - Đọc cái chú ý 2: giời hạn dịch bit [MỞ MẮT CHO TO RA RỒI ĐỌC]
    - Bài này tôi để TITLE là "MỘT SỐ VỀ BITWISE" chứ không phải TẤT CẢ VỀ BITWISE

    Nếu cậu giỏi, thích văn vẹo người khác thì sao không làm hẳn một bài hướng dẫn chia sẻ mọi người đi.
    None!

  9. #9
    Ngày gia nhập
    09 2008
    Bài viết
    19

    Trước tiên, xin lỗi vì mấy bài post kia làm bạn nổi nóng. Nhưng mình không thích vặn vẹo người khác kiểu này (nhất là với những bạn nhiệt tình - bạn review lại các post của mình sẽ thấy). Thiệt tình, tại diễn đàn không có nút Thanks, chứ không mình đã Thanks bạn trước khi post mấy post kia thì chắc bạn không hiểu lầm vậy.

    Số nguyên âm thì mình hoàn toàn đồng ý là nó ít khi được làm việc với các toán tử xử lý bit.
    Còn trường hợp kia, vì cái mình làm cũng có dính nhiều tới bitwise, nên mình hay gặp nó, và chưa giải thích được vì sao nó thế, chỉ định post lên và hỏi bạn (và mấy bạn khác) xem vì sao thôi mà (với lại để mấy bạn khác lưu ý về trường hợp đặc biệt này). Và mình cũng xin lỗi vì cái ví dụ mình đưa ra là SAI. Mình đặt lại vấn đề thế này:
    Code:
    int a, b;
    a = 1;
    b = a >> 32;
    Vì mình rất thích bitwise, nên thay vì đem chia, mình thường xài phép dịch bit. Ở đây đáng lẽ ra "a >> 32" thì bằng "a / (2^32)", rõ ràng luôn = 0 (và không vi phạm cái giới hạn ở chú ý 2 bạn đưa ra). Mà tại sao nó vẫn là 1? g++ cho 1 warning: right shift count >= width of type. Mình nghĩ là khi right shift >= max bit của biến thì nó sẽ không dịch nữa, nhưng nếu vậy thì hơi củ chuối nhỉ?

  10. #10
    Ngày gia nhập
    09 2006
    Nơi ở
    /usr/share/.hack@
    Bài viết
    1,433

    Trích dẫn Nguyên bản được gửi bởi hieusua Xem bài viết
    Trước tiên, xin lỗi vì mấy bài post kia làm bạn nổi nóng. Nhưng mình không thích vặn vẹo người khác kiểu này (nhất là với những bạn nhiệt tình - bạn review lại các post của mình sẽ thấy). Thiệt tình, tại diễn đàn không có nút Thanks, chứ không mình đã Thanks bạn trước khi post mấy post kia thì chắc bạn không hiểu lầm vậy.

    Số nguyên âm thì mình hoàn toàn đồng ý là nó ít khi được làm việc với các toán tử xử lý bit.
    Còn trường hợp kia, vì cái mình làm cũng có dính nhiều tới bitwise, nên mình hay gặp nó, và chưa giải thích được vì sao nó thế, chỉ định post lên và hỏi bạn (và mấy bạn khác) xem vì sao thôi mà (với lại để mấy bạn khác lưu ý về trường hợp đặc biệt này). Và mình cũng xin lỗi vì cái ví dụ mình đưa ra là SAI. Mình đặt lại vấn đề thế này:
    Code:
    int a, b;
    a = 1;
    b = a >> 32;
    Vì mình rất thích bitwise, nên thay vì đem chia, mình thường xài phép dịch bit. Ở đây đáng lẽ ra "a >> 32" thì bằng "a / (2^32)", rõ ràng luôn = 0 (và không vi phạm cái giới hạn ở chú ý 2 bạn đưa ra). Mà tại sao nó vẫn là 1? g++ cho 1 warning: right shift count >= width of type. Mình nghĩ là khi right shift >= max bit của biến thì nó sẽ không dịch nữa, nhưng nếu vậy thì hơi củ chuối nhỉ?
    biến kiểu int trong g++ là 4 bytes (32 bit) => right shift tối đa là 31 nháy.
    Bạn thử cho nó dịch phải 31 nháy và 1 nháy xem nó ra bao nhiêu...

    Tớ test thử:
    C++ Code:
    1. #include <stdio.h>
    2.  
    3. int main(void)
    4. {
    5.     int a, b;
    6.     a = 1;
    7.    
    8.     b = a >> 1;
    9.     printf("1 bit:\t b = %d \n", b);
    10.    
    11.     b = a >> 2;
    12.     printf("2 bit:\t b = %d \n", b);
    13.  
    14.     b = a >> 31;
    15.     printf("31 bit:\t b = %d \n", b);
    16.  
    17.     b = a >> 32;
    18.     printf("32 bit:\t b = %d \n", b);
    19.  
    20.     b = a >> 33;
    21.     printf("33 bit:\t b = %d \n", b);
    22.  
    23.     return 1;
    24. }

    Kết quả:
    C++ Code:
    1. 1 bit:   b = 0
    2. 2 bit:   b = 0
    3. 31 bit:  b = 0
    4. 32 bit:  b = 1
    5. 33 bit:  b = 0
    6. Press any key to continue . . .

    Thử lại với giá trị khác: lấy a = 3: thì kết quả là:
    Code:
    1 bit:   b = 1
    2 bit:   b = 0
    31 bit:  b = 0
    32 bit:  b = 3
    33 bit:  b = 1
    Press any key to continue . . .
    Thay với bất kì giá trị nào của a cũng đều thế này.

    Đưa ra kết luận:

    + Nếu giới hạn dịch vượt quá kích thước của kiểu dữ liệu thì phép dịch sẽ bị luân hồi, tức là dịch lại từ đâu.

    Ví dụ: kiểu int = 4 bytes = 32 bits => dịch tối đa 31 nháy (0->31). Từ 32 trở lại nó sẽ dịch ngược lại từ đầu tức là: a >> 0 == a >> 32; a >> 1 == a >> 33 .... (==: kí hiệu tương đương).

    Test thử sẽ rõ:
    C++ Code:
    1. #include <stdio.h>
    2.  
    3. int main(void)
    4. {
    5.     char a = 13;
    6.    
    7.     if((a >> 1) == (a >> 33))
    8.         printf("TRUE \n");
    9.  
    10.     return 1;
    11. }

    OK?
    Đã được chỉnh sửa lần cuối bởi Xcross87 : 27-10-2008 lúc 03:33 PM.
    None!

Các đề tài tương tự

  1. Bitwise operator được sử dụng như thế nào?
    Gửi bởi hura trong diễn đàn Thắc mắc lập trình C/C++/C++0x
    Trả lời: 4
    Bài viết cuối: 09-02-2011, 03:58 PM

Quyền hạn của bạn

  • Bạn không thể gửi đề tài mới
  • Bạn không thể gửi bài trả lời
  • Bạn không thể gửi các đính kèm
  • Bạn không thể chỉnh sửa bài viết của bạn