Tải bản đầy đủ (.doc) (5 trang)

Kỷ thuật xử lí Bit trong Pascal

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (109.86 KB, 5 trang )

Hệ đếm nhị phân trong máy tính
những bài toán hay về xử lý bit
Con người thường xử lý những bài toán bằng hệ đếm thập phân, nhưng có lẽ hệ đếm nhị phân lại là hệ đếm được
ưa thích hơn với những chiếc máy tính. Trong PC của bạn, các con số được thể hiện bằng các bit dưới dạng nhị
phân (0,1). Khi chúng ta nhập các con số duới dạng thập phân, máy sẽ xẽ xử lý và đưa về hệ nhị phân dưới dạng
các bit mà chúng ta có thể tạm hiểu là 0 và 1. Và chỉ tới khi xuất dữ liệu ra (màn hình hoặc tệp văn bản), các số
mới được thể hiện lại ở dạng thập phân. Mọi tệp trong máy thực chất là dòng các byte, trong đó có những byte giữ
vị trí đặc biệt dùng để điều khiển việc hiển thị.
Một số người có thể đã hiểu ít nhiều về bit và các bài toán xử lý bit, một số người thì không. Nhưng điều đó không
phải là quan trọng, khi mà điều quan trọng là chúng ta sẽ đề cập đến một vấn đề tưởng chừng như rất phức tạp
(đối với những người chưa biết nhiều về nó), nhưng thật ra lại thật là đơn giản mà hiệu quả lại rất cao trong khi xử
lý những bài toán hay và khó. Sau đây là những thông tin sơ lược về bit trong PC.
- Trong PC, mỗi số nguyên đều được biểu diễn ở hệ nhị phân bởi một dãy các bit 0 và 1.
- Các bit được mã số với những số hiệu từ phải sang trái.
7 6 5 4 3 2 1 0
- 1byte=8bit
- 1word=16bit
- Hàm sizeof (x) = số byte của số nguyên x.
- Các phép toán xử lý bit:
+ NOT x : phép đảo bit, đổi các giá trị trong mỗi bit của x từ 0->1,1->0.
+ x OR y : Phép cộng logic trên các bit.Thực hiện trên từng cặp bit tương ứng của các toán hạng theo bảng sau.
+ x AND y : Phép nhân logic trên các bit. Thực hiện trên từng cặp bit tương ứng của các toán hạng theo bảng sau.
+ x XOR y : Phép cộng logic trên các bit.Thực hiện trên từng cặp bit tương ứng của các toán hạng theo bảng sau.
+ x SHR i : Phép dịch phải, cho giá trị có được từ số nguyên x sau khi dịch sang phải i bit.
+ x SHL i : Phép dịch trái, cho giá trị có được từ số nguyên x sau khi dịch sang trái i bit.
Trên đây là một số phép toán làm việc trên các bit mà ta hay dùng, trên cơ sở đó, ta xây dựng được một số hàm,
thủ tục hay dùng sau.
- Hàm lấy bit.
Function LayBit(x:word; i:byte):byte;
Begin
LayBit:=(x SHR i) and 1


End;
Hàm trả về giá trị là bit thứ i của số nguyên x.
- Thủ tục bật bit.
Procedure BatBit(Var x:word; i:byte);
Begin
X:=x OR (1 SHL i)
End;
Thủ tục gán trị 1 cho bit thứ i trong số nguyên x.
- Thủ tục tắt bit.
Procedure TatBit(Var x:word; i:byte);
Begin
X:=x AND (NOT(1 SHL i))
End;
Thủ tục gán trị 0 cho bit thứ i trong số nguyên x.
- Hàm Lấy số.
Function LaySo(x:word;j,i:byte):byte;
Var
K:byte;
Begin
K:= (8*sizeof(x) - j - 1);
LaySo := (x SHL k) SHR (i+k)
End;
Hàm trả về giá trị là số tạo bởi các bit từ trái sang phải, từ j -> i của số x với điều kiện 8*sizeof(x)> j ≥ i ≥ 0.
Tiếp đến, chúng ta sẽ giải quyết một số bài toán khá hay về xử lý bit.
Bài toán: Sắp xếp dãy.
Cho tệp Data.dat gồm các số nguyên không âm nhỏ hơn 500 000 đôi một khác nhau. Hãy xắp tệp theo thứ tự tăng
dần và đưa ra tệp Result.dat.
Bài toán trên khiến ta cảm thấy khó chịu về giới hạn dữ liệu của nó, nếu ta nghĩ đến việc dùng mảng để lưu trữ và
xắp xếp thuần tuý thì quả là ngớ ngẩn bởi vì bộ nhớ 64K chẳng thấm tháp vào đâu và riêng việc xắp xếp đã chiếm
mức thời gian kỉ lục rồi. Ta cũng có thể dùng phương pháp xắp xếp ngoài Merge Sort (dùng file để sắp xếp), tuy

nhiên, đây không phải là giải pháp hữu hiệu vì vấn đề thời gian. Tuy nhiên, phương pháp sắp xếp đánh dấu bằng
một vài thủ thuật dùng bit thô sơ lại cho ta một kết quả khá là mĩ mãn. Ta chỉ cần dùng một mảng A kiểu byte với
khoảng 63000 phần tử là thừa đủ để xử lý bài toán này. Ta tưởng tượng mảng A là một đoàn tầu, và mỗi toa tầu là
một phần tử có 8 chỗ ngồi, chỗ ngồi được đánh dấu là 1 nếu có người ngồi, là 0 nếu ngược lại. Ban đầu đoàn tầu
không có người ngồi, ta gán mảng bằng 0. Và với mỗi phần tử đọc từ file ra, ta đánh dấu bit tương ứng trong mảng
cho tới khi hết file bằng thủ tục batbit. Để lấy kết quả ghi ra file, ta dùng function laybit. Sau đây là chương trình
thể hiện thuật toán:
{$A+,B-,D+,E+,F-,G-,I+,L+,N-,O-,P-,Q+,R+,S+,T-,V+,X+}
PROGRAM XAP_XEP_DAY_VOI_DU_LIEU_LON;
Const
Datin = 'Data.dat';
Datout = 'Result.dat';
Bt=8;
MAX=63000;
Var
a:array[0..MAX] of byte;
f:text;
Procedure Finish;
Var i,j:longint;
Function LayBit(x,j:longint):byte;
Begin
LayBit:=(x shr j) and 1;
End;
Begin
Assign(f,DATOUT);rewrite(f);
For i:=0 to max do
For j:=0 to bt-1 do
If LayBit(a[i],j)=1 then Write(f,(i*bt+j),' ');
Close(f)
End;

Procedure Start;
Var i,tg:longint;
Procedure BatBit(x,y:longint);
Begin
A[x]:=a[x] or (1 shl y)
End;
Begin
Fillchar(a, sizeof (a), 0);
Assign(f,DATIN);reset(f);
While not seekeof(f) do
Begin
Read(f,tg);
BatBit(tg div bt,tg mod bt)
End;
Close(f)
End;
BEGIN
Start;
Finish
END.
Một số bài tập tương tự.
Bài số 1: Trộn tệp.
Cho 2 tệp ′In1.dat′ và ′In2.dat′ chứa các số nguyên không âm có thể rất lớn (không lớn hơn 500 000). Hãy tạo tệp
′Out.dat′ chứa các số có mặt trong 2 tệp trên, tuy nhiên, không được trùng nhau.
Bài số 2: Tỉa xâu.
Cho file văn bản Str.inp gồm nhiều dòng, mỗi dòng không quá 30 kí tự, chỉ chứa hai kí tự ″ * ″ và ″ ″. Hãy loại bỏ
bớt các dòng giống nhau rồi in kết quả ra file ″Str.out″ gồm các dòng khác nhau.
Bài số 3: Mã số nhân viên
Tổng giám đốc một công ty X nổi tiếng là người kĩ lưỡng. Ông ta thực hiện việc quản lý nhân viên của
mình bằng cách gán cho mỗi nhân viên một mã số. Công ty có N nhân viên thì mỗi nhân viên i (i=1, 2,…,N)

có một mã số. Mã số là một số nguyên dương (hai nhân viên khác nhau phải có mã số khác nhau). Do bận đi
công tác một thời gian dài ở nước ngoài nên ông ta giao lại quyền quản lý cho một người khác. Khi ông trở
về, công ty đã có thay đổi số lượng nhân viên, khi tiếp nhận thêm nhân viên mới, ông ta yêu cầu muốn biết
mã số nhỏ nhất có thể gán cho nhân viên mới.
Yêu cầu:
Cho N mã số của các nhân viên trong công ty. Hãy tìm mã số nhỏ nhất chưa xuất hiện trong N mã số
đã cho.
Dữ liệu vào từ tệp văn bản CODE.INP
+ Dòng đầu là số N (1<N<=30.000)
+ N dòng tiếp theo, dòng thứ i ghi số ai (i=1..N, 1<=ai<=10
9
)
Kết quả ghi ra tệp văn bản CODE.OUT một số duy nhất là mã số tìm được
Ví dụ ( Hình bên)
CODE.INP CODE.OUT
7
6
5
9
1
3
4
2

×