Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Ruby

Master Ruby's Bitwise Toolbox: Toán Tử, Ứng Dụng & Thủ Thuật

Bạn có thể trọn đời xây Rails apps mà không bao giờ cần bitwise operators. Nếu mới lập trình, có thể không biết "bitwise" nghĩa là gì.

Nhưng khi bạn quan tâm đến systems nơi efficiency quan trọng và resources limited, bitwise operations trở nên crucial. Chúng dùng rộng rãi trong network protocols, cryptography, Unix file permissions và embedded systems.

Ngoài ra, để thực sự hiểu computer làm gì như cộng hai số, bạn phải hiểu bitwise operations.

Vì Ruby và nhiều languages khác có native support, chúng là tool tuyệt vời thêm vào toolbox, dù chỉ để hiểu khi gặp chúng trong tương lai.

Bài này cover: bitwise operations là gì, examples ứng dụng, cách dùng tốt nhất trong Ruby. Bắt đầu.

Bitwise Operations Là Gì?

Ở lowest level trong computer, chỉ có 1s và 0s, gọi là bits. Mọi operation khác trong Ruby cuối cùng lưu thành 1s và 0s, nhưng software transform chúng back-and-forth giữa thứ ta thấy và thứ thực sự lưu. Ví dụ, string "hello" lưu thành chuỗi 1s và 0s.

Bitwise operations cho phép access trực tiếp bits đó, thường represent numbers, và làm "gì đó" với chúng. Một số operations giúp implement features elegant và efficient hơn.

Hai aspects quan trọng: chúng cực kỳ effective lưu information (dùng bits trực tiếp), và rất fast execution.

Basic behavior: có set bits, apply operator. Cũng dùng operators với hai sets bits. Xem operations:

NOT Bitwise Operation

Unary operation, chỉ apply cho một set bits, đơn giản: replace 1s thành 0s và ngược lại. Symbol: ~.

~101000 = 010111

AND Bitwise Operation

Áp dụng cho hai sets bits; symbol &; logic:

1 & 1 = 1
1 & 0 = 0
0 & 1 = 0
0 & 0 = 0

Với hai equal-length sets bits, result là apply logic cho từng pair:

0110 AND 0111
-----
0110

Trong Ruby:

25.to_s(2) # 11001
30.to_s(2) # 11110
(25 & 30).to_s(2) # 11000

OR Bitwise Operation

Tương tự AND, operation khác áp dụng cho hai sets bits là bitwise OR. Symbol |, logic:

1 | 1 = 1
1 | 0 = 1
0 | 1 = 1
0 | 0 = 0

Nếu có 1 ở bất kỳ bên nào, result 1, ngược lại 0. Xem OR với nhiều bits:

0110 OR 0111
-----
0111

Trong Ruby:

25.to_s(2) # 11001
30.to_s(2) # 11110
(25 | 30).to_s(2) # 11111

Practical Example 1: Permissions

Có thể tự hỏi tại sao operations này useful. Chúng có vẻ low-level. Có thể bạn không plan làm network protocols, graphics hay cryptography.

Nhưng bạn chắc làm permissions trước. Permissions là area bitwise operations rất useful. Hãy tưởng tượng permissions system users perform actions trên document:

  • View
  • Edit
  • Delete
  • Invite other users

Model actions thành roles:

  • Assistant: view và edit.
  • Observer: chỉ view.
  • Author: tất cả actions.

Model như thế nào? Làm sao biết user có role? Cách dùng bitwise operations.

Lưu một set bits cho mỗi user represent permissions:

(Bắt đầu từ bên phải)
1st bit: View
2nd bit: Edit
3rd bit: Delete
4th bit: Invite other users

Ví dụ:

0001 = Chỉ view document.
0011 = View và edit.
1001 = View, không edit, không delete, invite others.

Khi đã set values cho users, fast comparisons với permission muốn check. Check user có edit được không, dùng bitwise AND:

# Bit mask. Chỉ chứa value muốn check, bit 2 cho editing.
EDIT_PERMISSION_MASK = 0b0010

# Method check nhanh:
def can_edit_document?(user_permissions)
  (EDIT_PERMISSION_MASK & user_permissions) != 0
end

Nếu bitwise AND cho khác 0, bit đó set:

0010 AND 1101
----
0000 == 0 => không có permission

0010 AND 1110
----
0010 != 0 => có permission

Apply logic tương tự cho permission khác bằng cách đổi vị trí bit check, constants và methods:

VIEW_PERMISSION_MASK     = 0b0001
EDIT_PERMISSION_MASK     = 0b0010
DELETE_PERMISSION_MASK   = 0b0100
INVITE_PERMISSION_MASK   = 0b1000

Thêm, dynamically define permissions và store new permissions với quick bit check.

Ví dụ Assistant chỉ view và edit, permissions = 0011. Store trong DB, check assistant có perform action không với methods trên.

ASSISTANT_MASK = VIEW_PERMISSION_MASK | EDIT_PERMISSION_MASK # = 0011

# Optionally, method check user là assistant:
def is_assistant?(user)
  (user.permissions == ASSISTANT_MASK)
end

Nếu familiar, vì đây là approach dùng cho file permissions trong Unix-based systems.

Practical Example 2: Positions In A Team

Dùng bitwise operations thêm 😉. Case common: positions trong sports team hoặc job positions. Chọn basketball team.

Basketball có 5 positions: Point guard, Shooting guard, Small forward, Power forward, Center.

Assign bits cho từng position:

00001 Point guard
00010 Shooting guard
00100 Small forward
01000 Power forward
10000 Center

Trong Ruby:

POINT_GUARD_POSITION     = 0b00001
SHOOTING_GUARD_POSITION  = 0b00010
SMALL_FORWARD_POSITION   = 0b00100
POWER_FORWARD_POSITION   = 0b01000
CENTER_POSITION          = 0b10000

POINT_GUARD_POSITION | SHOOTING_GUARD_POSITION | SMALL_FORWARD_POSITION | POWER_FORWARD_POSITION | CENTER_POSITION
# = 31

Check whole team present:

# p1...p5 là positions của từng player
is_full_team_present = (p1 | p2 | p3 | p4 | p5 == 31)

Tại sao? Bitwise OR operation, nếu có tất cả positions, kết quả: 11111.

# OR bitwise operation
00001 | 00010 | 00100 | 01000 | 10000
-----
11111

11111 = 31, vì 2^0 + 2^1 + 2^2 + 2^3 + 2^4 = 31.

Không strictly related bitwise, nhưng với data modeling này cũng check nếu two players có thể exchange. Rất đơn giản:

def can_be_exchanged?(player1, player2)
  player1.position == player2.position
end

XOR

Operation khác với hai sets bits là XOR, symbol ^.

XOR = exclusive OR, logic:

1 ^ 1 = 0
1 ^ 0 = 1
0 ^ 1 = 1
0 ^ 0 = 0

Result = 1 chỉ khi một trong hai bits = 1; nếu cả hai bằng nhau thì 0.

Operation này dùng trong algorithms compare number với chính nó, vì x ^ x = 0.

Shifts

Group operations "move" bits left/right trong set. Giải thích.

Bit shift: move bits one direction, left hoặc right:

00010111 left-shift <------- 00101110
10010111 right-shift -------> 11001011

Move/shift bits n times. Left shift applied to number 5 twice trong Ruby:

5.to_s(2)  # 101
(5 << 2).to_s(2)  # 10100

Left shift = <<. Right shift = >>:

5.to_s(2)  # 101
(5 >> 2).to_s(2)  # 1

Chỉ còn 1, vì bits "0" và "1" từ 101 bị discarded.

Chia 2 Với Right Shift

Thú vị: right shift cho kết quả chia 2:

10.to_s(2)  # 1010
(10 >> 1).to_s(2)  # 101
10 >> 1  # 5

Nhân 2 Với Left Shift

Tương tự, left shift nhân 2:

10.to_s(2)  # 1010
(10 << 1).to_s(2)  # 10100
10 << 1  # 20

Nhanh Check Odd/Even

Ví dụ đơn giản bitwise operation real fast và easy.

AND operation với 1, chỉ 1. Số 0s tùy computer, và 1. Với 2:

2 = 00000010
& 00000001
-------------
00000000

Với 4:

4 = 00000100
& 00000001
-------------
00000000

Với 5?

5 = 00000101
& 00000001
-------------
00000001

Ra 1. Đoán được ý nghĩa?

AND với 1, nếu even → 0, odd → 1. Dùng fact này tạo methods Ruby:

def is_odd?(number)
  number & 1
end
def is_even?(number)
  is_odd?(number) == 0
end
# Hoặc:
def is_even?(number)
  (number & 1) == 0
end

Muốn đi sâu hơn, trải nghiệm mind-blowing moments với bits, check bitwise hacks collection.

Kết Luận

Bitwise operations khó follow nếu chưa gặp, nhưng khi familiar bạn better prepared deal với existing/future projects dùng chúng. Plus, tool mới khi plan solution cho problem trong code.