Trường ĐẠI HỌC CÔNG NGHIỆP THỰC PHẨM TP HỒ CHÍ MINH Khoa CÔNG NGHỆ THÔNG TIN Tiểu luận Môn Kiến Trúc Máy Tính Đề tài THỰC HIỆN CÁC PHÉP TÍNH CỘNG, TRỪ, NHÂN, CHIA SỐ NHỊ PHÂN 32 BIT 1 MỤC LỤC 1 Lý thu[.]
Trang 1Trường: ĐẠI HỌC CÔNG NGHIỆP THỰC PHẨM
TP HỒ CHÍ MINH
Tiểu luận:
Môn: Kiến Trúc Máy Tính
Đề tài :
THỰC HIỆN CÁC PHÉP TÍNH CỘNG, TRỪ,
NHÂN, CHIA SỐ NHỊ PHÂN 32 BIT
Trang 2MỤC LỤC
1 Lý thuyết 3
1.1 Số nhị phân 3
1.2 Các phép toán trên số nhị phân 3
1.2.1 Phép cộng 3
1.2.2 Phép trừ 4
1.2.3 Phép nhân 4
1.2.4 Phép chia 5
2 Ý tưởng cho thuật toán 6
2.1 Phép cộng 6
2.2 Phép trừ 7
2.3 Phép nhân 8
2.4 Phép chia 10
Trang 31 Lý thuyết.
1.1 Số nhị phân.
Có các hệ số có cơ số riêng như: Binary (hệ nhị phân), Octagonal (hệ bát phân), và Hexagonal (hệ thập lục phân), Decimal (hệ thập phân) Chúng được sử dụng rộng rãi trong hệ thống số Trong đó hệ nhị phân chiếm ưu thế trong hệ thống máy tính
Trong hệ nhị phân, chúng ta chỉ có hai chữ số, 1 và 0
Các chữ số 1 và 0 trong ký hiệu nhị phân có cùng ý nghĩa như trong
ký hiệu thập phân:
Trong số nguyên có dấu A: được biểu diễn bởi n bit như sau:
a n−1 a n−2 … a2a1a0
A là số dương: bit a n−1=0
A là số âm: bit a n−1=1;
Các bit còn lại biểu diễn độ lớn như số nguyên không dấu
1.2 Các phép toán trên số nhị phân.
1.2.1 Phép cộng.
Phép tính đơn giản nhất trong hệ nhị phân là tính cộng Cộng hai đơn
vị trong hệ nhị phân được làm như sau:
0 + 0 = 0
0 + 1 = 1
1 + 0 = 1
1 + 1 = 0 (nhớ 1)
Ví dụ:
Trang 41.2.2 Phép trừ.
Phép tính trừ theo quy chế tương tự:
0 − 0 = 0
0 − 1 = 1 (mượn 1)
1 − 0 = 1
1 − 1 = 0
Một đơn vị nhị phân được trừ với một đơn vị nhị phân khác như sau:
1.2.3 Phép nhân.
Phép tính nhân trong hệ nhị phân cũng tương tự như phương pháp làm trong hệ thập phân Hai số A và B được nhân với nhau bởi những tích số cục bộ: với mỗi con số ở B, tích của nó với một con số trong
A được tính và viết xuống một hàng mới, mỗi hàng mới phải chuyển dịch vị trí sang bên trái, hầu cho con số cuối cùng ở bên phải đứng cùng cột với vị trí của con số ở trong B đang dùng Tổng của các tích cục bộ này cho ta kết quả tích số cuối cùng
Vì chỉ có 2 con số trong hệ nhị phân, nên chỉ có 2 kết quả khả quan trong tích cục bộ:
Nếu con số trong B là 0, tích cục bộ sẽ là 0
Nếu con số trong B là 1, tích cục bộ sẽ là số ở trong A
Ví dụ, hai số nhị phân 1011 và 1010 được nhân với nhau như sau:
Trang 51.2.4 Phép chia.
Tính chia nhị phân cũng tương tự như phép chia trong hệ thập phân
Ở đây ta có số bị chia là 11011, hoặc 27 trong số thập phân, số chia là 101, hoặc 5 trong số thập phân Cách làm tương tự với cách làm trong số thập phân Ở đây ta lấy 3 số đầu của số bị chia 110 để chia với số chia, tức là 110, được 1, viết lên trên hàng kẻ Kết quả này được nhân với
số chia, và tích số được trừ với 3 số đầu của số bị chia Số tiếp theo là một con số 1 được hạ xuống để tạo nên một dãy số có 3 con số, tương tự với
số lượng các con số của số chia:
Quy luật trên được lặp lại với những hàng số mới, tiếp tục cho đến khi tất cả các con số trong số bị chia đã được dùng hết:
Trang 6Phân số của 11011 chia cho 101 là 101, như liệt kê phía trên đường kẻ, trong khi số dư còn lại được viết ở hàng cuối là 10B=2D Trong
hệ thập phân, 27 chia cho 5 được 5, dư 2
2 Ý tưởng cho thuật toán.
*** Thuật toán chỉ áp dụng cho phép tính số nguyên không dấu.
2.1 Biến dung chung và Các hàm con
***Mảng kết quả nói chung và các mảng khác trong thuật toán này được miêu tả như sau: (mảng A có a phần tử)
int no = 0;
int nho = 0;
int [] A = new int [32]; int a;
int [] B = new int [32]; int b;
string X, Y; //chuỗi lấ! y được từ ỗ "Nhập sỗ! nhị phấn 1" và "Nhập sỗ! nhị phấn 2" bằng cách click btnBackUp
int x, y; //sỗ! bit ban đấ4 u lấ! y được từ string X,Y
int [] MangX = new int [32]; //sau khi gọi hàm StringToArray thì được
ma ;ng MangA,MangB
int [] MangY = new int [32];
int KiemTra( int [] A, int a)
//không phai sô nhị phân thì return 1
void PhepCong( int [] A, int [] B, int [] C, int c)
//cộng 2 mang A, B có cùng sô bit c, kết qua lưu vào mang C
void PhepTru( int [] A, int [] B, int [] C, int c)
//trừ 2 mang A, B có cùng sô bit c, kết qua lưu vào mang C
void HoanVi( ref int u, ref int v)
//đôi chô 2 bit, dùng trong hàm DaoMang
Trang 7void DaoMang( int [] A, int a) //đao mang
void CharToInt( char a, out int gt)
//chuyến 1 bit kiếu char thành 1 bit kiếu int
void StringToArray( string TextBox, int [] A, out int a)
//Mang thu đuược Chỉ sô từ trái 0 đô? ng thời xác định được sô bit ban đâ? u cua sô nhị phân
int ss2Bit( int a, int b)
//nếu bit a lớn hơn bit b thì return 1, ngược lại return -1
int soSanh( int [] A, int [] B)
//so sanh 2 mang cung 32 bit bang nhau return 0, A>B return 1, A<B return -1
int nhan2Bit( int a, int b)
void BackUp()
//sao lưu lại dữ liệu ban đâ? u dùng cho phép nhân/chia
void LayMang( string TextBox, int [] A, out int a)
//từ một chuôi, chuyến thành mang kí tự 32 bit
2.2 Phép cộng
Gọi hàm con void PhepCong(int [] A, int [] B, int [] C, int c, ref int nho)
Tạo mảng C là mảng kết quả thu được có 32 bit.
- Hai mảng A,B cùng 32 bit được đánh số 0,1,2….,31 từ phải qua
trái
- Sử dụng vòng lặp for,mảng C chạy từ phần tử i=0 đến phần tử
i=31, cộng từng cặp bit, trả kết quả vào C[i] dựa vào biến “nho” khởi tạo ban đầu bằng 0:
- Nếu “nho” bằng 1:
Trang 8- Sau khi thực hiện xong vòng lặp, được mảng kết quả là C có 32
bit và biến “nho” trả về có giá trị 1 hoặc 0
- Tùy cách biến đổi mà chuyển mảng C thành chuổi Text để xuất ra
ngoài
- Nếu tại i=31, “nho=1”=> tràn số
2.3 Phép trừ.
Gọi hàm con void PhepTru(int [] A, int [] B, int [] C, int c, ref int no)
Tạo mảng C là mảng kết quả thu được có 32 bit.
- Hai mảng A,B cùng 32 bit được đánh số 0,1,2….,31 từ phải qua
trái
- So sánh hai mảng để biết có trừ được hay không:
Trang 9int ss2Bit(int a, int b) //nếu bit a lớn hơn bit b thì
return 1, ngược lại return -1
{
if (a > b)
return 1;
else
return -1;
}
- Không trừ được nếu mảng A< mảng B=>thong báo tràn số.
- Sử dụng vòng lặp for chạy từ phần tử i=0 đến phần tử i=31, trừ
các cặp bit dựa vào biến “no” khởi tạo ban đầu bằng 0
Trang 10- Thực hiện xong vòng lặp ta được C là mảng kết quả 32 bit và biến
“no” trả về mang giá trị 1 hoặc 0
- Nếu “no” trả về bằng 1=> tràn số.
2.4 Phép nhân.
Nhân mảng MangX và mảng MangY có x,y phần tử là các bit của sô nhị phân Mảng này lấy được khi nhấn vào button “Nhập xong”
Việc Backup này nhầm mục đích kiểm tra dữ liệu ban đầu nhập vào( có vượt quá 32 bit, có nhập số khác 0 và 1 hay không), sao lưu lại, đồng thời biến đổi dữ liệu đó thành mảng gồm các bit số nhị phân:
void BackUp() //sao lưu lại dữ liệu ban đâ? u dùng cho phép
nhân/chia
{
X = txtNhap1.Text;
Y = txtNhap2.Text;
StringToArray(X, MangX, out x); //mang đang có chỉ sô đánh từ bến trái là 0
DaoMang(MangX, x); //đao mang đế được mang đánh sô 0
từ bến phai
StringToArray(Y, MangY, out y);
DaoMang(MangY, y);
}
BackUp có gọi hàm con là StringToArray() để chuyển chuổi nhập vào thành mảng kí tự:
void StringToArray(string TextBox, int[] A, out int a) //Mang thu đucợ Chỉ sô từ trái 0 đô? ng thời xác định được sô bit ban đâ? u cua
sô nhị phân
{
string l = TextBox;
a = l.Length;
Char [] L = Convert ToString(l).ToCharArray(); //chuoi thanh mang ki tu
for (int i = 0; i < a; i++)
{
char j = L[i];
int gt;
CharToInt(j, out gt); //chuyen kieu ki tu sang so nguyen
A[i] = gt;
Trang 11}
}
Và biến mảng kí tự thành mảng số nguyên gồm các số 0 và 1 là các bit của số nhị phân thông qua hàm con CharToInt():
Gọi hàm DaoMang() để được mảng đánh số nhưng mong muốn: do sau khi chuyển thì mảng thu được:
Vd: chuổi là 1010101111 Sau khi chuyển được mảng
void DaoMang(int[] A, int a)
{
for (int i = 0, j = a - 1; i < j; i++, j )
HoanVi(ref A[i], ref A[j]);
} //đao mang
Gọi đảo mảng thì được:
- Trong phép toán nhân này, ta dùng MangX có x phần tử, MangY
có y phần tử
- Ta tạo mảng C có c phần tử đều là bit 0, trong đó c=x+y
- Dùng vòng lặp for lấy từng phần tử của MangY:i chạy từ 0-> y-1.
Với mõi giá trị i, ta tạo mới 1 mảng tam có c bit đều bằng 0
Lấy phần tử đầu tiên của MangY nhân lần lượt với tất cả các phần tử của MangX-> ghi kết quả vào mảng tam-> cộng kết quả của mảng tam với mảng C-> được C mới
Lần lượt thực hiện cho đến khi hết số phần tử của MangY( y-1) Sau mỗi làn thực hiện ta cộng kết quả của tam
và C vừa thực hiện ở trên( cứ mỗi lần như vậy tam sẽ lùi lại
1 đơn vị)=> kết quả cuối cùng là C
Trang 12- Tùy cách biến đổi mà chuyển mảng C thành chuổi Text để xuất ra ngoài
- Nếu c=x+y>32 => tràn số
*** với cách tính như vậy, sẽ gặp lỗi khi MangY có 1 bit và MangX có 32 bit vì c=32+1=33>32 Nên ta có trường hợp ngoại lệ của phép nhân này,
có sử dụng các hàm con dung để kiểm tra:
int KTNgoaiLe(int[] A, int a) //nhân/chia 1 mang với mang có giá trị 0 hoạc 1
{
if (a == 1)
return 1;
else
return 0;
}
if ((KTNgoaiLe(MangX, x) == 1) || (KTNgoaiLe(MangY, y) == 1))
{
if (KTNgoaiLe(MangX, x) == 1)
{
if (MangX[0] == 0)
for ( int i = 0; i < 32; i++)
C[i] = 0;
else
for ( int i = 0; i < 32; i++)
C[i] = B[i];
}
else
{
if (MangY[0] == 0)
for ( int i = 0; i < 32; i++)
C[i] = 0;
else
for ( int i = 0; i < 32; i++)
C[i] = A[i];
}
string kq = "" ;
for ( int i = 31; i >= 0; i )
kq += C[i];
txtXuatKQ.Text = kq;
}
2.5 Phép chia.
- B1 :
Mảng MangX( sao lưu từ A) với x bit(đây là số bit ban đầu), chỉ số
0 đánh từ bên phải.
Mảng MangY(sao lưu từ B) với y bit(y là số bit bang đầu), chỉ số 0
đánh từ bên phải.
Trang 13Mảng tam khởi tạo với y-1 bit ban đầu lấy từ mảng MangX:
• tam[0]=MangX[(x-1)-0]
• tam[1]=MangX[(x-1)-1]
• tam[y-2]=MangX[(x-1)-(y-2)] =MangX[x-y+1]
while (j < y - 1) // lay tam[] tu MangX[] co y-1 bit
{
tam[j] = MangX[x - 1 - j];
j++;
}
- B2:
Cho vòng lặp for bắt đầu từ bit tiếp theo của MangX (x-y) đến hết Lấy lần lược từng nhóm (y+j) bit từ mảng MangX( mảng tam) với j:
0->x-y so sánh với mảng MangY, và thực hiện phép trừ :
+ Nếu tam[]<=MangY[]: C[i]=0
Nếu tam[]<MangY[]: tam[] như cũ
Nếu tam[]=MangY[]: tam[] có tất cả bit đều bằng 0
+ Ngược lại: C[i]=1, tam[]=tam[]-MangY
Thực hiện vòng lặp này thì số phần tử mảng tam sẽ tăng dần từ (y-1) đến x bit trong khi MangY thì vẫn y bit không đổi, nên không gọi được PhepTru() Để gọi PhepTru() thì tam[] và MangY[] phải cùng số bit nên để dễ dàng và không ảnh hưởng đến việc thực hiện phép nhân, ta dùng mảng CopyY với n_CopyY lấy từ MangY[]:
Trang 14for ( int k = x - y; k >= 0; k ) //tiep tuc lay ptu tu MangX de du y bit
{
tam[j] = MangX[k];
DaoMang(tam, j + 1);
if (soSanh(tam, CopyY) >= 0)
{
C[c] = 1;
if (soSanh(tam, CopyY) > 0)
PhepTru(tam, B, tam, j + 1, ref no);
else
for ( int i = 0; i < j + 1; i++)
tam[i] = 0;
}
else
{
C[c] = 0;
}
DaoMang(tam, j + 1);
c++; j++;
CopyY[n_CopyY] = 0;
n_CopyY++;
}
VD:
BƯỚC 1:
• MangX – x bit ( ví dụ x=10): 1011010010:
MangX[9
]
MangX[8
]
MangX[7 ]
MangX[6 ]
MangX[0 ]
• CopyY - n_CopyY bit( ví dụ 5 bit): 10111:
• Tam[] lấy từ MangX
CopyY[4] CopyY[3
]
CopyY[0]
MangX[9] MangX[8] MangX[7] MangX[6]
Trang 15BƯỚC 2:
•Tam[] lấy thêm 1 bit nữa từ MangX
Đảo mảng tam[] lại để thực
hiện trừ cho MangY
***Trong ví dụ này
tam<CopyY, nên được
C[0]=0và tam sau khi trừ
không đổi
CopyY[] khi đã tăng
bit(đọc ở bước lặp tiếp
theo)
BƯỚC LẶP TIẾP THEO:
Đảo mảng tam lại
để thêm bit mới
vào
Đảo mảng để thực
hiện PhepTru()
***Mảng tam 5bit, mảng CopyY ở vòng lặp trước chỉ 4 bit, không thể gọi PhepCong() Nên ta phải tăng số bit n_CopyY lên mà không ảnh hưởng bằng cách n_CopyY++ và gán giá trị CopyY[n-CopyY]=0; thực hiện ở trên
MangX[9] MangX[8] MangX[7] MangX[6] MangX[5]
MangX[5] MangX[6] MangX[7] MangX[8] MangX[9]
changed changed changed changed changed
0 CopyY[4] CopyY[3] CopyY[0]
changed changed changed changed changed MangX[4]
MangX[4] changed changed changed changed changed
Trang 16Tam[] sau khi trừ
CopyY[] khi tăng bit
(phải tang bit sau
mõi lần trừ để tam
và CopyY có cùng
số bit
Tiếp tục hết vòng lặp.
for ( int k = x - y; k >= 0; k ) //tiep tuc lay ptu tu MangX de du y bit
{
tam[j] = MangX[k];
DaoMang(tam, j + 1);
if (soSanh(tam, CopyY) >= 0)
{
C[c] = 1;
if (soSanh(tam, CopyY) > 0)
PhepTru(tam, B, tam, j + 1, ref no);
else
for ( int i = 0; i < j + 1; i++)
tam[i] = 0;
}
else
{
C[c] = 0;
}
DaoMang(tam, j + 1);
c++; j++;
CopyY[n_CopyY] = 0;
n_CopyY++;
}
Kết quả thu được là mảng C và số dư là mảng tam
Phép chia này không tràn số tuy nhiên sẽ nhận được thông báo “không chia được” nếu MangY mang giá trị 0
0 changed changed changed changed changed
0 0 CopyY[4] CopyY[3] CopyY[0
]
Trang 17int KTChia0(int[] A, int a) //kiếm tra xem mang A có phai toàn bit 0, dùng trong chia 1 sô với 0
{
for (int i = 0; i < a; i++)
if (A[i] == 1)
return 0;
return 1;
}