1. Trang chủ
  2. » Luận Văn - Báo Cáo

Báo cáo tìm hiểu các thuật toán thực hiện trên số lớn như phép toán cộng, trừ, nhân, chia 2 số nguyên lớn

19 1,6K 8

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 19
Dung lượng 207,3 KB

Nội dung

BÀI TẬP NHÓMCHỦ ĐỀ: CÀI ĐẶT THƯ VIỆN SỐ LỚN Tìm hiểu các thuật toán thực hiện trên số lớn như phép toán cộng, trừ, nhân, chia 2 số nguyên lớn.. LỜI MỞ ĐẦUTuy rằng trong cuộc sống và côn

Trang 1

BÀI TẬP NHÓM

CHỦ ĐỀ: CÀI ĐẶT THƯ VIỆN SỐ LỚN

( Tìm hiểu các thuật toán thực hiện trên số lớn như phép toán

cộng, trừ, nhân, chia 2 số nguyên lớn).

Giáo viên: HÀ THỊ THANH

THÀNH VIÊN NHÓM

1 Vũ Văn Hậu

2 Lê Mạnh Cường,

3 Hoàng Trọng Quỳnh

4 Lê Văn Trường

5 Nguyễn Hoàng Chung

MỤC LỤC

Trang 2

LỜI MỞ ĐẦU 3

Phần 1: 4

THAO TÁC CỘNG 4

1.1 THUẬT TOÁN 4

PHẦN 2 7

PHÉP TRỪ SỐ NGUYÊN LỚN 7

2.1 Giải thuật trừ: 7

2.2 Về chương trình 7

Phần 3 9

PHÉP NHÂN 2 SỐ LỚN 9

3.1 Giải thuật nhân: 9

3.2 Tương tự như phép cộng ta có đoạn chương trình sau: 9

Phần 4 11

PHÉP CHIA 2 SỐ LỚN 11

4.1 Giải thuật chia: 11

4.2 Về chương trình ta có như sau: 11

PHẦN 5 14

MỘT SỐ HÀM BỔ TRỢ 14

5.1 Hàm bỏ tất cả các số 0 ở đầu 1 chuỗi số nguyên 14

5.2 Hàm lấy về chuỗi số lơn hơn trong 2 chuỗi 14

5.3 Hàm chuyển số thập phân thành số nguyên 15

PHẦN 6 17

GIỚI THIỆU VỀ CHƯƠNG TRÌNH 17

1 Giao diện chính của trương trình 17

2 Cách sử dụng: 17

LỜI KẾT 18

Trang 3

LỜI MỞ ĐẦU

Tuy rằng trong cuộc sống và công việc bình thường chúng ta chỉ có nhu cầu tính toán với các số đến hàng tỷ (9 chữ số) hay đến tỷ tỷ (18 chữ số) với phần thập phân cũng chỉ cần chính xác đến 4,5 số là đã nhiều, nhưng trong một số nghành khoa học đòi hỏi sự chính xác cao như khoa học nguyên tử, vũ trụ, thì nhu cầu tính toán với những con số lớn hơn nữa với phần thập phân có khi cần chính xác đến vài chục chữ số sau dấu phẩy là hoàn toàn cần thiết Hoặc đơn giản hơn nó chỉ

là một đề bài tập hay bài kiểm tra trong lớp học công nghệ thông tin của chúng ta.

Tư tưởng của thuật toán này là không sử dụng những kiểu dữ liệu số sẵn có của C#, vì tất cả các kiểu dữ liệu này đều bị giới hạn Thay vào đó, ta sử dụng kiểu

dữ liệu string, sử dụng các hàm xử lý chuỗi để nó có thể tính toán theo đúng những nguyên tắc cộng trừ nhân chia số học.

Nhóm chúng em sau một thời gian tìm hiểu và đã xây dựng một chương trình tính toán đơn giản các số nguyên lớn trên (C#) với nhiều chữ số Kết quả đã được test trên nhiều thiết bị máy tính khác, như máy tính của windows đều cho kết quả rất chính xác.

Trang 4

Phần 1:

THAO TÁC CỘNG

1.1 THUẬT TOÁN

Thông thường, khi cộng hai số có nhiều chữ số, chúng ta thực hiện từ phải qua trái Với mỗi lần cộng, kết quả của nó còn được cộng với giá trị nhớ của lần trước đó và đồng thời cũng xác định giá trị nhớ mới Ở đây, vì các số được lưu theo chiều ngược lại nên chúng ta thực hiện từ trái qua phải, tức là từ đầu đến cuối xâu.

Giả sử chúng ta có một số nguyên (lớn) a=32145; sẽ có rất nhiều cách lưu trữ số nguyên này (do ta quy định), ở đây ta sẽ đưa ra cách lưu số này qua mảng 1 chiều ngược, cụ thể như sau: a[0]=5, a[1]=4, a[2]=1, a[3]=2 và a[4]=3; nhưng khi xuất thì lại xuất ngược lại so với cách lưu trữ!, số nguyên này có 5 chữ số, khi nhập (input) số này vào chương trình thì chúng ta sẽ dùng dấu khoảng trắng (space) để ngăn cách các chữ số và nhập bình thường theo thứ tự thông thường, ví dụ

a=32145 sẽ được nhập vào như sau: 3 2 1 4 5.

Vậy nếu cần thực hiện phép toán Cộng hai số a và b sau đó lưu vào mảng c (kết quả) thì ta đề xuất các bước (c=a+b)

1.2 CÁC BƯỚC THỰC HIỆN

- Bước 1: Loại bỏ các chữ số 0 vô nghĩa ở 2 mảng a và b.

- Bước 2: Thêm chữ số 0 ở đầu mảng có độ dài ngắn hơn để 2 mảng có cùng độ dài (tức là nếu a=1234, b=21 thì chúng ta thấy: mảng b có 2 phần tử; mảng a có 4 phần tử; vậy để hai mảng này có số phần tử bằng nhau thì chúng ta thêm 2 chữ số 0 nữa vào mảng b; lúc này b=0021).

- Dùng một biến nhớ, để lưu trữ số nhớ sau mỗi bước tính Ta lưu giá trị vào một mảng INT đã được khởi tạo có giá trị là 0

Bước 3: Đảo ngược chuỗi và tính toán

Bước 4: Xuất kết quả ta đảo ngược chuỗi kết quả.

Trang 5

THEO CÁC BƯỚC Ở TRÊN TRƯƠNG TRÌNH THỰC HIỆN CỘNG SẼ

CÓ CODE NHƯ SAU:

//hàm cộng 2 số nguyên cực lớn

#region addInt()

public string addInt(string strNum1, string strNum2)

{

//B1:tìm ra chuối ngắn hơn và thêm số 0 vào chuối cho đu"

if(strNum1.Length > strNum2.Length)

strNum2 = strNum2.PadLeft(strNum1.Length, '0');

else if(strNum2.Length > strNum1.Length)

strNum1 = strNum1.PadLeft(strNum2.Length, '0');

//Bước 2: đưa vào ma"ng int int[], thực hiên chuyê"n đố"i các số vê' thành dạng int32 đê" tiện cho việc tính toán nêu số quá lớn

int[] arrNum1 = new int[strNum1.Length];

int[] arrNum2 = new int[strNum2.Length];

for(int i=0; i<strNum1.Length; i++)

{

arrNum1[i] = Convert.ToInt32(strNum1.Substring(i,1));

}

for(int i=0; i<strNum2.Length; i++)

{

arrNum2[i] = Convert.ToInt32(strNum2.Substring(i,1));

}

//Bước 3: Đa"o ngược chuối và tính toán

Array.Reverse(arrNum1);

Array.Reverse(arrNum2);

// Tính toán

int[] arrResult = new int[strNum1.Length+1];

int phanbu = 0;

for(int i=0; i<strNum1.Length; i++)

{

arrResult[i] = arrNum1[i] + arrNum2[i] + phanbu;

if(arrResult[i] >= 10)

{

arrResult[i] -= 10;

phanbu = 1;

}

else

phanbu = 0;

}

if(phanbu==1)

arrResult[arrResult.Length-1] = 1;

//Đa"o ngược chuối kêt qua" và hiê"n thị kêt qua" trên màn hình

Array.Reverse(arrResult);

Trang 6

StringBuilder strbd = new StringBuilder(arrResult.Length);

foreach(int i in arrResult)

strbd.Append(i);

string strResult = "";

if(phanbu==1)

strResult = strbd.ToString();

else if(phanbu==0)

strResult = strbd.ToString().Substring(1);

return strResult;

}

#endregion

Trang 7

PHẦN 2 PHÉP TRỪ SỐ NGUYÊN LỚN 2.1 Giải thuật trừ:

Giống như cộng, chúng ta cũng thực hiện từ phải qua trái Với mỗi lần trừ,

đề phòng chữ số của số bị trừ nhỏ hơn nên ta cứ vay tạm một chục Nếu lần trước

đã vay rồi thì lần này phải trừ đi Nhưng chỉ đáng vay nếu kết quả sau khi trừ là bé hơn 10, còn lớn hơn 10 là không phải vay Dưới đây ta xem rằng a >= b.

2.2 Về chương trình.

Vì là phép trừ nên khi tính toán ta cần phải nhận biết số trừ và số bị trừ, sẽ có một hàm so sánh như sau:

//1 Tim so lon hon

for(int i=0; i<strNum1.Length; i++)

{

if(arrNum1[i] > arrNum2[i])

{

strNumBig = strNum1;

break;

}

else if(arrNum1[i] < arrNum2[i])

{

strNumBig = strNum2;

break;

}

}

if(strNumBig == "")

{

txtResult.Text = "0"

else //neu 2 so ko bang nhau

{

if(strNumBig == strNum1)

strNumSmall = strNum2;

else

strNumSmall = strNum1;

Trang 8

Sau đó đưa phần các phần tử vào mảng INT[]

//Dua vao mang int[]

int[] arrNumBig = new int[strNumBig.Length];

int[] arrNumSmall = new int[strNumSmall.Length];

for(int i=0; i<strNumBig.Length; i++)

{

arrNumBig[i] = Convert.ToInt32(strNumBig.Substring(i,1)); }

for(int i=0; i<strNumSmall.Length; i++)

{

arrNumSmall[i] = Convert.ToInt32(strNumSmall.Substring(i,1)); }

Cuối cùng là đảo ngược chuỗi , tính toán và cho kết quả ra màn hình:

//Dao nguoc chuoi

Array.Reverse(arrNumBig);

Array.Reverse(arrNumSmall);

//so mu~ cua 10 chinh la chi so phan tu trong mang int[]

int[] arrResult = new int[strNumBig.Length];

int phanbu = 0;

for(int i=0; i<strNumBig.Length; i++)

{

arrNumSmall[i] = arrNumSmall[i] + phanbu;

if(arrNumBig[i] >= arrNumSmall[i])

{

arrResult[i] = arrNumBig[i] - arrNumSmall[i];

phanbu = 0;

}

else

{

arrResult[i] = arrNumBig[i]+10 - arrNumSmall[i];

phanbu = 1;

}

}

//Dao nguoc chuoi Result

Array.Reverse(arrResult);

StringBuilder strbd = new StringBuilder(arrResult.Length);

foreach(int i in arrResult)

strbd.Append(i);

Trang 9

Phần 3 PHÉP NHÂN 2 SỐ LỚN 3.1 Giải thuật nhân:

Thông thường, khi nhân a với b, chúng ta thực hiện từ phải qua trái Mỗi lần

sẽ nhân một chữ số của b với số a và đặt kết quả dịch sang trái 1 chữ số Nhưng trong mỗi lần đó chúng ta lại lần lượt nhân từng chữ số của a với chữ số nói trên của b Cũng như phép cộng, kết quả cũng phụ thuộc việc nhớ của lần nhân trước và xác định giá trị nhớ mới Việc nhận này được thực hiện từ trái qua phải đó.

3.2 Tương tự như phép cộng ta có đoạn chương trình sau:

// nhập các số đê" tiên hành nhân

#region Phep nhan

private void btnMul_Click(object sender, System.EventArgs e)

{

if(!checkInput())

{

MessageBox.Show("Input Number is not valid");

txtNumber1.Focus();

}

else

{

//Phep nhan 2 so nguyen

string strNum1 = strTempN1[0];

string strNum2 = strTempN2[0];

//Dua vao mang int[]

int[] arrNum2 = new int[strNum2.Length];

for(int i=0; i<strNum2.Length; i++)

{

arrNum2[i] = Convert.ToInt32(strNum2.Substring(i,1));

}

//mang string luu tru cac so hang

string[] arrstr = new string[strNum2.Length];

int x = 0;

for(int i=strNum2.Length-1; i>=0; i )

{

arrstr[x] = Mul(strNum1, arrNum2[i]);

//them so 0 o cuoi chuoi

arrstr[x] = arrstr[x].PadRight(arrstr[x].Length + x, '0');

Trang 10

}

//cong cac so hang nguyen bang ham addInt() voi nhau

string strResult = "";

for(int i=0; i<arrstr.Length; i++)

{

strResult = addInt(strResult, arrstr[i]);

}

}

#endregion

Trang 11

Phần 4 PHÉP CHIA 2 SỐ LỚN 4.1 Giải thuật chia:

Thông thường, khi chia a với b, chúng ta thực hiện từ trái qua phải Lần đầu tiên lấy nhóm có số chữ số bằng số chữ số của b, các lần sau đó chỉ lần lượt hạ một

số xuống phần dư Thay vì nhẩm xem được mấy lần, ở đây chỉ việc thử lần lượt từ

0 đến có thể Vì chúng ta lưu ngược nên ta thực hiện từ phải qua trái Hàm sau thực hiện chia a cho b, đặt kết quả vào c và phần dư.

4.2 Về chương trình ta có như sau:

//Phep chia - btnDiv_Click

#region Phep chia

private void btnDiv_Click(object sender, System.EventArgs e)

{

if(!checkInput())

{

MessageBox.Show("Input Number is not valid");

txtNumber1.Focus();

}

else

{

string strNum1 = txtNumber1.Text;

string strNum2 = txtNumber2.Text;

// Thuc hien phep chia nhu chia 2 so nguyen

-if(strNum1 == strNum2)

{

txtResult.Text = "1";

}

else //khi 2 so ko bang nhau

{

string strResult = "";

//neu so bi chia (strNum1) lon hon

if(NumBigger(strNum1, strNum2) == strNum1)

{

string strtemp = strNum1.Substring(0, strNum2.Length);

Trang 12

string strBookmark = strtemp;

string phandu="";

bool flag = true;

while(phandu != "0" || strtemp != "00")

{

//ket qua co toi da 80 chu so (tinh ca dau )

//result: max 80 char

if(strResult.Length == 80)

break;

string[] arrKetqua = DivInt(strtemp, strNum2).Split(

new char[]{'~'});

strResult += arrKetqua[0];

phandu = arrKetqua[1];

// MessageBox.Show("~"+arrKetqua[0]+"~"+arrKetqua[1]+"~");

if(strBookmark.Length < strNum1.Length) //van con so de ha

{

strBookmark = strNum1.Substring(0, strBookmark.Length+1);

//ha so xuong de tiep tuc chia

strtemp = phandu + strNum1.Substring(strBookmark.Length-1,1);

if(strtemp.IndexOf('0')==0) //Ex: 0.34/0.03

strtemp = strtemp.Substring(1);

}

else if(strBookmark.Length == strNum1.Length) //het so de ha

{

if(flag == true)

{

strResult += ".";

flag = false;

}

//them 0 vao sau phan du de tiep tuc chia

strtemp = phandu + "0";

//neu da them 0 ma strtemp van nho hon so bi chia

if(NumBigger(strtemp, strNum2) == strNum2)

{

// strResult += "0";

strtemp = phandu + "0";

}

//neu so chia lon hon

else if(NumBigger(strNum1, strNum2) == strNum2)

{

strResult = "0.0";

while(NumBigger(strNum1, strNum2) == strNum2)

{

strNum1 += "0";

strResult += "0";

}

bool flag = true;

if(strNum1.Length > strNum2.Length)

Trang 13

flag = false;

}

strResult = strResult.Substring(0, strResult.Length-2);

//Thuc hien tuong tu phan tren ===============

string strtemp = strNum1.Substring(0, strNum2.Length);

string strBookmark = strtemp;

string phandu="";

while(phandu != "0")

{

//ket qua co toi da 40 chu so (tinh ca dau )

if(strResult.Length == 40)

break;

string[] arrKetqua = DivInt(strtemp, strNum2).Split(

new char[]{'~'});

strResult += arrKetqua[0];

phandu = arrKetqua[1];

if(strBookmark.Length < strNum1.Length) //van con so de ha

{

strBookmark = strNum1.Substring(0, strBookmark.Length+1);

//ha so xuong de tiep tuc chia

strtemp = phandu + strNum1.Substring(strBookmark.Length-1,1); }

else if(strBookmark.Length == strNum1.Length) //het so de ha

{

//them 0 vao sau phan du de tiep tuc chia

strtemp = phandu + "0";

//neu da them 0 ma strtemp van nho hon so bi chia

if(NumBigger(strtemp, strNum2) == strNum2)

{

// strResult += "0";

strtemp = phandu + "0";

}

}

if(flag == false)

{

strResult = "0." + strResult.Substring(3);

}

}

//neu co dau o cuoi thi bo di

if(strResult.IndexOf('.') == strResult.Length-1)

strResult = strResult.Substring(0, strResult.Length-1);

txtResult.Text = strResult;

// txtResult.Text = "~"+strNum1 +"~"+ strNum2 +"~" + strResult;

}

#endregion

Trang 15

PHẦN 5 MỘT SỐ HÀM BỔ TRỢ

Trong quá trình tính toán các số lớn khá phức tạp, vậy để đơn giản hơn trong quá trình tính toán, ta kết hợp một số hàm bổ trợ để trong những chương trình con chúng ta có thể sử dụng chúng để tính toán.

5.1 Hàm bỏ tất cả các số 0 ở đầu 1 chuỗi số nguyên.

//Ham bo tat ca cac so 0 o dau 1 chuoi so nguyen

#region MyRemove()

public string MyRemove(string strnum)

{

char[] ch = strnum.ToCharArray();

int n=0;

for(int i=0;i<ch.Length; i++)

{

if(ch[i] == '0')

n++;

else

break;

}

return strnum.Substring(n);

}

#endregion

5.2 Hàm lấy về chuỗi số lớn hơn trong 2 chuỗi

//Ham lay ve chuoi so lon hon trong 2 chuoi, = nhau thi tra ve ""

#region NumBigger() - so nguyen

private string NumBigger(string strNum1, string strNum2)

{

string strNumBig = "";

if(strNum1.Length > strNum2.Length)

{

strNumBig = strNum1;

strNum2 = strNum2.PadLeft(strNum1.Length, '0');

}

else if(strNum2.Length > strNum1.Length)

{

strNumBig = strNum2;

strNum1 = strNum1.PadLeft(strNum2.Length, '0');

Trang 16

else if(strNum1.Length == strNum2.Length)

{

int[] arrNum1 = new int[strNum1.Length];

int[] arrNum2 = new int[strNum2.Length];

for(int i=0; i<strNum1.Length; i++)

{

arrNum1[i] = Convert.ToInt32(strNum1.Substring(i,1));

}

for(int i=0; i<strNum2.Length; i++)

{

arrNum2[i] = Convert.ToInt32(strNum2.Substring(i,1));

}

for(int i=0; i<strNum1.Length; i++)

{

if(arrNum1[i] > arrNum2[i])

{

strNumBig = strNum1;

break;

}

else if(arrNum1[i] < arrNum2[i])

{

strNumBig = strNum2;

break;

}

}

}

return strNumBig;

}

#endregion

5.3 Hàm chuyển số thập phân thành số nguyên

//ham chuyen so thap phan thanh so nguyen

//va lay ve vi tri dau tu ben phai sang

#region myConvert()

public string myConvert(string strnum)

{

string numpos = ""; //return dang 645437~4 hoac 849~0 (so~vitridau.)

if(strnum.IndexOf('.') < 0)

numpos = strnum + "~0";

else if(strnum.IndexOf('.') > 0)

{

string temp1 = strnum.Substring(0, strnum.IndexOf('.'));

string temp2 = strnum.Substring(strnum.IndexOf('.')+1);

numpos = temp1 + temp2 + "~" + temp2.Length.ToString();

}

Trang 17

return numpos;

}

#endregion

5.4 Hàm kiểm tra đầu vào.

#region kiem_tra_dau_vao()

public bool kiemtradauvao()

{

bool flag = true ;

string strNum1 = txtNumber1.Text;

string strNum2 = txtNumber2.Text;

Regex regexDou1 = new Regex ( @"^[1-9]+[0-9]*\.{0,1}[0-9]*[1-9]+$" );

Regex regexDou2 = new Regex ( @"^0{1}\.[0-9]*[1-9]+$" );

Regex regexInt = new Regex ( @"^[1-9]{1}[0-9]*$" );

Match m1 = regexInt.Match(strNum1);

Match m2 = regexInt.Match(strNum2);

Match m3 = regexDou1.Match(strNum1);

Match m4 = regexDou1.Match(strNum2);

Match m5 = regexDou2.Match(strNum1);

Match m6 = regexDou2.Match(strNum2);

if ((!m1.Success && !m3.Success && !m5.Success) ||

(!m2.Success && !m4.Success && !m6.Success))

flag = false ;

return flag;

}

#endregion

Ngày đăng: 10/04/2015, 15:43

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w