1. Trang chủ
  2. » Công Nghệ Thông Tin

Bài toán chuyển đổi cơ số

10 5,1K 28
Tài liệu đã được kiểm tra trùng lặp

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

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Bài Toán Chuyển Đổi Cơ Số
Tác giả Đoàn Phương Nam
Trường học Trường Đại Học
Chuyên ngành Tin học
Thể loại Bài báo
Định dạng
Số trang 10
Dung lượng 52,5 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Bài toán chuyển đổi cơ số

Trang 1

Chuyển đổi cơ số

Đoàn Phương Nam

Chúng ta đã có dịp làm quenvới xử lý số lớn ở các tập báo trước Trong bài báo này tôi xin được trao đổithêm với bạn đọc chủ đề trên thông qua bài toán chuyển đổi một số từ

cơ số nàysang cơ số khác Đây là một bài toán khá quan trọng và đầy lý thú Đối với conngười thì cơ số thập phân (cơ số 10) là rất quen thuộc, chúng ta thường thaotác, tính

toán trên hệ cơ số 10 Nhưng đối với máy tính thì khác, cơ số 10không phải là?sở

trường? mà lại làcơ số nhị phân (tức cơ số 2) Chính vì vậy bất kì ai học Tin học đều

phải hiểucơ số, biết cách chuyển một số từ cơ số này sang cơ số khác

Giới thiệu qua về cơ số

Trong hệ thống thập phân mộtsố có thể được phân tích bằng tổng của luỹ thừa 10 Như vậy: 2808 10 = 2*10 3+ 8*102 + 0*101 + 8*100

Cũng vậy, trong hệ cơ số kmột số M ở hệ cơ số k có thể phân tích bằng tổng luỹ thừa k

Ví dụ với k = 28thì 28928 = 2*282 + 8*281 + 9*280

Bài toán chuyển đổi cơ số S sang cơ số D

Cho một xâu W là biểu diễncủa một số ở cơ số S Hãy tìm biểu diễn của số đó ở cơ số D

(S, D <= 35).Nếu trong trường hợp cơ số lớn hơn 10 thì ký tự?A? tương ứng với số 10,

ký tự?B?tương ứng với số 11, , ký tự?Y?tương ứng với số 35.

Dữ liệu vàotrong file coso.inp códạng:

+ Dòng thứ nhất gồm hai số Svà D;

+ Dòng thứ hai là một xâu W(độ dài của xâu <101)

Kết quả rafile coso.out gồm một dòng duy nhấtlà một xâu ký tự, biểu diễn của số đó ở cơ

số D

Coso.out

35 10

XYXYXYXYXY

Coso.inp

2679667322982089

Trang 2

Thuật toán:

Để chuyển một số từ cơ số Ssang hệ cơ số D trước tiên ta đổi số đó sang hệ cơ số thập phân (cơ số 10) Sauđó đổi tiếp số vừa đổi sang cơ số D

- Để chuyển một số sang cơ sốthập phân, ta áp dụng trực tiếp cách phân tích đã giới thiệu

ở trên W= w1w2 wN= w1*SN-1 + w2*SN-2 + + wN*S0= ( ((w1*S+w2)*S+w3) )*S+wN Tatính theo độ ưu tiên trong ngoặc (vì tính như thế sẽ mất ít phép tính toánnhất) Vì W có thể rất lớn, như vậy từng giá trị trong ngoặc cũng có thể rấtlớn, ta không thể dùng các kiểu số có sẵn để lưu trữ mà phải dùng xâu để lưu.Để tính giá trị biểu thức trên ta phải thao tác hai loại phép toán đó là : nhânmột số lớn với S (S<=35) và cộng một số lớn với một số <=35

- Để chuyển một số từ cơ sốthập phân sang cơ số D, ta chia số đó cho D phần dư sẽ là ký

tự cuối cùng củabiểu diễn đó Sau đó ta lại lấy thương của phép chia vừa rồi chia tiếp cho D,phần dư nhận được sẽ là ký tự đứng sát trước của ký tự cuối cùng Cứ làm nhưvậy cho đến khi thương bằng không Như vậy để chuyển một số từ cơ số thập phânsang cơ số D ta phải có thao tác phép toán là: chia một số lớn cho số D(D<=35) và lấy dư

Trong bài viết 'Lập trình với các số Khổng lồ? củatác giả Lê Mạnh Dũng ở số 8 năm

2001, tác giả đã đề cập tới việc tính toán vớicác số lớn Song nếu áp dụng thuật toán đó

để giải bài này thì e rằng làm phứctạp bài toán và mất nhiều thời gian cài đặt cũng như thời gian chạy Vì thuậttoán mà tác giả Lê Mạnh Dũng đã đề cập là thuật toán xử lý hai

số lớn còn cácphép toán cần trong chương trình này là xử lý một số lớn với một số nhỏ

Thuật toán cộng một số lớn với một số nhỏ

function cong(x:string;num:longint): string;

var nho,tong,k :longint;

kq :string;

begin

kq:=x; nho:=num;{đặt số cần cộng vào nho}

for k:=length(x) downto 1 do

begin

tong:=ord(x[k])-48+nho;

nho:=tong div 10;

kq[k]:=char(tong mod 10+48);

Trang 3

if nho=0 then break;

end;

while nho>0 do

begin

kq:=char(nho mod 10+48)+kq;

nho:=nho div 10;

end;

cong:=kq;

end;

Thuật toán cộng trên đây chophép cộng một số lớn chứa trong kiểu string cộng với một

số lớn kiểu longint.Thuật toán này dễ cài đặt, dễ hiểu và hiệu suất cao Có một chú ý duy nhất lànho (nhớ) có thể lớn hơn 10

Thuật toán nhân một số lớn với một số nhỏ

functionnhan(x:string;num:longint):string;

var kq :string;

k,nho,tich :longint;

begin

nho:=0;kq:='';

for k:=length(x) downto 1 do

begin

tich:=num*(ord(x[k])-48)+nho;

nho:=tich div 10;

kq:=char(tich mod 10+48)+kq;

end;

Trang 4

while nho>0 do

begin

kq:=char(nho mod 10+48)+kq;

nho:=nho div 10;

end;

nhan:=kq;

end;

Thuậttoán nhân trình bày ở trên?y trang?thuật toán nhân với số có một chữ số Ta không cần quan tâm nó có bao nhiêu chữsố cứ coi nó chỉ là số có một chữ số Song cũng giống như thuật toán cộng nhớcó thể lớn Không đơn thuần nhớ chỉ là số có một chữ số Chính điều này làm takhó nhận ra thuật toán trên

Thuật toán chia một số lớn cho một số nhỏ

functionchiăx:string;num:longint;var du:integer):string;

var nho,k :longint;

kq:string;

begin

nho:=0; kq:='';

for k:=1 to length(x) do

begin

nho:=nho*10+ord(x[k])-48;

kq:=kq+char(nho div num+48);

nho:=nho mod num;

end;

du:=nho;

while (length(kq)>0)and(kq[1]='0') do delete(kq,1,1);

Trang 5

end;

Thuậttoán chia một số lớn cho một số nhỏ ở trên thao tác từ trái qua phải, mỗi lầnhạ một phần tử xuống, gộp vào biến nhớ, thực hiện phép chia trực tiếp được (vìsố chia là một số nhỏ) Nếu là phép chia hai số lớn thì việc này không thể thựchiện được vì số chia cũng là

số lớn Do đó nếu muốn thực hiện phép chia hai sốlớn ta phải thử phần thương từ 0 đến 9

Nhưvậy ta đã có các công cụ quan trọng để giải bài toán cơ số Sau đây là chươngtrình cụ thể

{$A+,B-,D+,E+,F-,G-,I+,L+,N-,O-,P-,Q+,R+,S+,T-,V+,X+,Y+}

{$M 16384,0,655360}

uses crt;

const

max_cs = 35;

max = 40;

digit: string='0123456789ABCDEFGHIJKLMNOPQRSTUVWXY';

fi = 'coso.inp';

fo = 'coso.out';

var N_S,N_10 : string;

S,D : integer;

procedure docf;

var f :text;

begin

assign(f,fi);

reset(f);

readln(f,S,D);

Trang 6

close(f);

end;

functionnhan(x:string;num:integer):string; var kq :string;

k,nho,tich :integer;

begin

nho:=0;kq:='';

for k:=length(x) downto 1 do

begin

tich:=num*(pos(x[k],digit)-1)+nho; nho:=tich div 10;

kq:=digit[tich mod 10+1]+kq;

end;

while nho>0 do

begin

kq:=digit[nho mod 10+1]+kq;

nho:=nho div 10;

end;

nhan:=kq;

end;

functioncong(x:string;num:integer):string; var nho,tong,k :integer;

Trang 7

kq> :string;

begin

kq:=x;nho:=num;

for k:=length(x) downto 1 do

begin

tong:=pos(x[k],digit)-1+nho;

nho:=tong div 10;

kq[k]:=digit[tong mod 10+1];

if nho=0 then break;

end;

while nho>0 do

begin

kq:=digit[nho mod 10+1]+kq;

nho:=nho div 10;

end;

cong:=kq;

end;

functionchuyen10(x:string):string;

var kq:string;

k :integer;

begin

kq:='';

for k:=1 to length(x) dokq:=cong(nhan(kq,S),pos(x[k],digit)-1);

Trang 8

end;

functionchiăx:string;num:integer;var du:integer):string; var nho,k :integer;

kq:string;

begin

nho:=0;kq:='';

for k:=1 to length(x) do

begin

nho:=nho*10+pos(x[k],digit)-1;

kq:=kq+digit[nho div num+1];

nho:=nho mod num;

end;

du:=nho;

while (length(kq)>0)and(kq[1]='0') do delete(kq,1,1); chia:=kq;

end;

procedure chuyenD(x:string);

var s :array[1 1000]of char;

du,top :integer;

f :text;

begin

top:=0;

Trang 9

while x<>'' do

begin

x:=chiăx,D,du);

inc(top);

s[top]:=digit[dư1];

end;

assign(f,fo);

rewrite(f);

while top>0 do

begin

write(f,s[top]);

dec(top);

end;

close(f);

end;

BEGIN

docf;

N_10:=chuyen10(N_S);

chuyenD(N_10);

END

Trong trường hợp D nhỏ (ví dụD = 2) thì số chữ số ở hệ cơ số D là rất nhiều không chứa được vào xâu do đó chươngtrình đã xử dụng mảng s để lưụ

Chú ý là các thao tác cộng,trừ, chia trình bày ở trên chỉ thực hiện với số chữ số <255 (dùng kiểu xâu).Nếu bạn muốn thực hiện với số lớn hơn thì xử dụng mảng

Trang 10

Như vậy tôi đã cung cấp cho các bạn các phép toán xửlý số lớn với số nhỏ Điều tôi muốn thảo luận với các bạn là tuỳ vào từngtrường hợp cụ thể ta lựa chọn các công cụ để giải quyết với độ phức tạp ítnhất, cài đặt nhanh nhất, đơn giản nhất

Bài tập áp dụng

1 Hãy tính N! (N <= 2000)

2 Tính MN (M, N <= 100)

3 Tính tổ hợp chập k của N (k < N < 100)

Ngày đăng: 07/09/2012, 10:30

TỪ KHÓA LIÊN QUAN

w