PDA

View Full Version : [C] Bài tập mô phỏng máy tính Fx 500 MS !



a4bk
12-09-2006, 03:38 PM
Kì này em có môn Kĩ thuật lập trình C ,thấy giáo cho bài tập lớn đại khái mô phỏng máy tính Fx 500MS ,hiện ra màn hình như sau :


> X=1
1
> Y=2 (nhập số lệu cho biến X và Y)
2


> X (hỏi giá trị của X)
1
> Z (hỏi giá trị của Z)
biến Z chưa khởi tạo


> 5*6+2-3 (tính giá trị biểu thức)
29

> X*2-Y (tính giá trị biểu thức)

0 (kết quả )

> Z=5*X-Y (khởi tạo Z và gán giá trị )
3
> X++ (tăng X lên 1 đơn vị )
2

> Z+Y=5+6*X (thông báo lỗi cú pháp nếu cần )
Error

> GPTB3 (lệnh chạy chương trình giải phương trình bậc 3 1 ẩn)
......

> GHPT (giải hệ)
.....
"dấu nhắc > là cần thiết "

Ngoài ra nếu có thêm các tính năng khác như ma trận, số phức thì càng tốt . Còn tính toán chác chỉ dùng +,-,X,: là hết .


Mới học C nên chưa hình dung được phải làm như thế nào xin mod và các anh em cho ý kiến tham khảo !

Cám ơn trước !

hailoc12
12-09-2006, 09:35 PM
Vấn đề trong bài này có lẽ chỉ là việc tính biểu thức, về vấn đề này bạn hãy tham khảo về Ký pháp nghịch đảo BaLan, trong quyển Cấu trúc dữ liệu và giải thuật đã được Post lên đâu đó trong diễn đàn này, Cách cài đặt cụ thể thì để mai mình post.
Còn đây là cách giải quyết riêng của mình khi gặp bài toán tương tự như vậy:
Ta xây dựng lên một Hàm gọi là Đouutien(statement) trả lại phép toán có độ ưu tiên thấp nhất trong biểu thức.
Gọi Left là phần biểu thức bên trái phép toán đó, Right là phần biểu thức bên phải. Ta xây dựng hàm tính toán giá trị biểu thức như sau
F(biểu thức);
If là biểu thức hằng Then F= giá trị cụ thể
Else
Tìm phép toán có độ ưu tiên thấp nhất
Áp dụng phép toán đó cho F(Left) và F(Right); Kết quả trả về cho F

Như bạn có thể thấy đây là thủ tục đệ quy, cài đặt khá đơn giản.
Đây là ví dụ: 56*1+4
Tính F(56*1+1)
Phép toán có độ ưu tiên thấp nhất là +
Do đó F(56*1+1)= F(56*1)+F(1)
F(1)=1
F(56*1)
Phép toán có độ ưu tiên thấp nhất là *
Do đó F(56*1)= F(56)*F(1)

a4bk
13-09-2006, 03:07 PM
Vấn đề trong bài này có lẽ chỉ là việc tính biểu thức, về vấn đề này bạn hãy tham khảo về Ký pháp nghịch đảo BaLan, trong quyển Cấu trúc dữ liệu và giải thuật đã được Post lên đâu đó trong diễn đàn này,

Vâng ,cám ơn bác ,em đã tìm và xem qua quyển đó như vậy với giải thuật tính giá trị biểu thức trong sách thì bài này hướng giải quyết của em cơ bản là như sau :
1 : Nhập biểu thức cần tính dưới dạng xâu kí tự
2 : Check ,kiểm tra xâu xem biểu thức nhập vào có đúng cú pháp không ,xem đây là biểu thức thường hay biểu thức gán,là câu lệnh hay biểu thức ,thông báo lỗi nếu có .
3 : Nếu là biểu thức gán thì xem biến gán đã có hay chưa ,chưa có thì khởi tạo ,lưu lại ,tách phần biểu thức và biến gán .Nếu là câu lệnh thì chạy hàm được gọi !
4 : Xác định biểu thức cần tính giá trị ,chuyển biểu thức từ dạng trung tố sang tiền tố hoặc hậu tố (ở đây em chọn dạng hậu tố ) .Tính giá trị biểu thức hậu tố tương ứng !
5: Trả lại kết quả ,xử lý tương ứng,in ra màn hình !

Như vậy vấn đề chính là ở bước 2 ,xây dựng hàm check ,bước 3 là việc lưu và các biến đã khởi tạo ,bước 4 thì em cũng chưa giải quyết được hẳn bởi vì giải thuật trong sách là dùng stack còn hiện giờ mình đang xử lý xâu .
Em sẽ cài đặt stack bằng mảng rồi chuyển xâu qua mảng tính toán ,trong C xâu được làm từ mảng nên chắc dùng luôn xâu cũng được nhưng hơi rối !

Cuối cùng là xử lý câu lệnh , giải hệ phương trình (khử Gauss) và giải phương trình bậc 3 ( công thức Các nô ) thì chắc không có vấn đề còn giải phương trình bặc 4 1 ẩn em tạm thời chưa giải quyết được .


Ta xây dựng lên một Hàm gọi là Đouutien(statement) trả lại phép toán có độ ưu tiên thấp nhất trong biểu thức.
Gọi Left là phần biểu thức bên trái phép toán đó, Right là phần biểu thức bên phải. Ta xây dựng hàm tính toán giá trị biểu thức như sau
F(biểu thức);
If là biểu thức hằng Then F= giá trị cụ thể
Else
Tìm phép toán có độ ưu tiên thấp nhất
Áp dụng phép toán đó cho F(Left) và F(Right); Kết quả trả về cho F


Cách của bác hoàn toàn tự nhiên ,trước khi đọc sách cấu trúc dữ liệu và giải thuật em cũng nghĩ như vậy .Đọc xong rồi em thấy nên theo cách xử lý trong sách vì khi tính toán đơn giản,rõ ràng hơn,đỡ nhầm lẫn và quan trọng là tránh dùng đệ quy .

Cách cài đặt cụ thể thì để mai mình post

Bác không cần phải vội đâu , đây là bài tập lớn đến tận gữa tháng 10 mới nộp ,anh em ta bàn bạc thêm chút nữa rồi cài đặt ;)! .

Cám ơn bác !

a4bk
27-09-2006, 05:10 PM
Ui ! 2 tuần rùi bận làm bài không lên chẳng thấy ai ghóp ý nữa cả !
Hiện giờ chương trình đã hoàn thành gồm các chưc năng chính sau :
1. Tính giá trị biểu thức (như đã mô tả ở trên )
2. Giải phương trình phi tuyến
bao gồm giải phương trình bậc 2,3,4 giải ra cả nghiệm phức lẫn nghiệm thực .Và có thể tìm được nghiệm của pt bất kì nhập vaod từ bàn phím = pp newton
3.Giải hệ n ẩn
4. Ma trận
chỉ có các chức năng cơ bản như :tính định thức,tính ma trận nghịch đảo,nhân ma trận,giải phương trình ma trận AX=B
5. Số phức
Chương trình nhập vào 1 biểu thức số phức như máy tình 570 có điều chỉ hạn chế là số phức phải để trong dấu ngoặc ví dụ (5.2+3i)*(1+2i)-(3i)
Không xử lý được hoàn toàn như máy tính ,rất mong mọi người đóng ghóp dùm cho giải thuật phần này
6.Vẽ đồ thị hàm số nhập vào từ bàn phím
Hàm nhập vào chỉ được chứa ẩn và số + các phép toán bình thường như lũy thưa + - * / .Không dùng được các hàm khác nhiều tham số .
Ngoài ra người dùng phải tự nhập vào khỏng cần vẽ dồ thị do phần ngày mình không xử lý được !


Hiện giờ em muốn thêm xử lý phân số ,hỗn số và các hàm nhiều tham số vào trong mục 1 nhưng chưa có giải thuật khả thi ,hy vọng các bác cho ý kiến !!

Chương trình nguồn hiện giờ 113K ai tham khảo có thể gửi tin nhấn cho mình qua nick yahhoo : a4bk . (hy vọng là như vầy không vy pham nội quy diễn đàn :D
)

mời bác hailoc vào ghóp ý tiếp cho em :)

nguyentuan2
27-09-2006, 05:36 PM
ở đây có ai biết
lex/yacc/antlr/sablecc
chỉ cho bạn nó giải bài này xem nào

bây giờ người ta giải bài này bằng phương pháp 'z' chứ không phải bằng phương pháp 'a' như bạn làm đâu

a4bk
27-09-2006, 05:43 PM
ở đây có ai biết
lex/yacc/antlr/sablecc
chỉ cho bạn nó giải bài này xem nào

bây giờ người ta giải bài này bằng phương pháp 'z' chứ không phải bằng phương pháp 'a' như bạn làm đâu
hic hic bạn ơi ,tớ không hiểu !(\'o)
phương pháp z và phương pháp a là cái gì cả ,nếu có thể rất mong bạn nói rõ !

hailoc12
27-09-2006, 06:35 PM
Để làm phức tạp hơn anh thử đọc cái này xem. Nó nói về nguyên lý để xây dựng các chương trình dịch, trong đó có phần phân tích cú pháp.

nguyentuan2
27-09-2006, 07:21 PM
tiếc quá, chương trình trước đây của mình viết bằn java, nói sơ qua về khả năng của nó

http://forums.congdongcviet.com/attachment.php?attachmentid=70&stc=1&d=1159358621

http://forums.congdongcviet.com/attachment.php?attachmentid=71&stc=1&d=1159358621

chương trình này sử dụng sablecc, mất 2 ngày để viết lõi tính toán, vài ngày nữa để hoàn tất giao diện và tương tác với người dùng

rất nhanh phải không, ai dùng cách này cũng nhanh vậy thôi, chẳng giỏi giang gì

thảo luận thêm đi các bạn, ai rành về lex/yacc thì cùng bàn luận, tui rất mong biết thêm về nó

a4bk
28-09-2006, 10:13 AM
Để làm phức tạp hơn anh thử đọc cái này xem. Nó nói về nguyên lý để xây dựng các chương trình dịch, trong đó có phần phân tích cú pháp.

Cám ơn bạn nhiều ,mình sẽ về đọc thử !


tiếc quá, chương trình trước đây của mình viết bằn java, nói sơ qua về khả năng của nó



chương trình này sử dụng sablecc, mất 2 ngày để viết lõi tính toán, vài ngày nữa để hoàn tất giao diện và tương tác với người dùng

rất nhanh phải không, ai dùng cách này cũng nhanh vậy thôi, chẳng giỏi giang gì

thảo luận thêm đi các bạn, ai rành về lex/yacc thì cùng bàn luận, tui rất mong biết thêm về nó

À..Vâng ...rất ...nhanh ,rất ...gọn,rất...tuyệt ,ai dùng cách này cũng ...nhanh vậy thôi .Chương trình của ông anh viết bằng Java thì tốt rồi ,có điều anh trình bày như thế này thì đàn em chẳng học hỏi được gì cả !

Em sẽ biết ơn anh rất nhiều nếu như anh trình bày sơ cho đàn em về cái thuật toán 'z' của anh ,nếu không thì code viết = C em còn biết ơn anh nhiều nữa !Y!:)

Còn chương trình của anh để em góp ý thêm cho nhé ! Anh có thấy cái chương trình máy tính của Win không anh ,dao diện ít ra phải như thế !
Vậy còn nhưng chức năng nâng cao khác của Casio Fx 570 MS như giải pt,giải hệ ,tính toán số phức,ma trận ,lưu biến , cao cấp hơn là vẽ đồ thị ....có vẻ là không có !):)T . Còn nữa ...;)

Hy vọng anh chỉ sơ cho em khi xử lý phân số hoặc các hàm nhiều biến số phức tạp khác như max(1,2),USCLN,sin,cos,ln...khi lập trình trong C .

nguyentuan2
29-09-2006, 11:02 AM
mình không có ý định phát triển nó thành 1 cái máy tính hoàn chỉnh, mà chỉ muốn thử bộ tính toán thôi, vì mục đích của mình là cho phép một chương trình lưu công thức trong DB, sau đó load lên cả data và công thức lên rồi tính toanns kkết quả, ví như bài toán thông kê chẳng hạn, đương nhiên không ai muốn sau này nếu thay đổi công thức thì phải thay đổi cả một chương trình tính toán, mà chỉ muốn thay công thức dạng text đã lưu trong DB thôi

Trở lại vấn đề là mình làm như thế nào
thứ quan trọng đáng kể nhất mình cần viết là:



Package expcalc;

Helpers

digit = ['0' .. '9'];
letter = [['a' .. 'z']+['A' .. 'Z']];
cr = 13;
lf = 10;
tab = 9;
ws = ' ';

Tokens

t_open = '(';
t_close = ')';
t_dot = '.';
t_comma = ',';
t_plus = '+';
t_pos = 'pos';
t_minus = '-';
t_neg = 'neg';
t_mul = '*';
t_div = '/';
t_power = '^';
t_exp = 'exp';
t_fact = '!';
t_log = 'log';
t_ln = 'ln';
t_lg = 'lg';
t_sin = 'sin';
t_cos = 'cos';
t_tan = 'tan';
t_cotan = 'cotan';
t_asin = 'asin';
t_acos = 'acos';
t_atan = 'atan';
t_acotan = 'acotan';
t_sqrt = 'sqrt';
t_sqr = 'sqr';
t_cub = 'cub';
t_cubrt = 'cubrt';
t_pi = 'PI';
t_e = 'E';

t_var = ('v' | 'V') (digit)* ;
t_num = digit+ (('E' | 'e') ('+' | '-')? digit+ | '.' digit+ (('E' | 'e') ('+' | '-')? digit+)?);
t_digits = digit+;
t_delim = (tab | ws | cr | lf)+ ;

Ignored Tokens
t_delim;

Productions

exp = operand;

operand = operand1;

operand1 = {operand2} operand2 |
{plus} operand1 t_plus operand2 |
{minus} operand1 t_minus operand2;

operand2 = {operand3} operand3 |
{neg} t_minus operand2 |
{pos} t_plus operand2;


operand3 = {operand4} operand4 |
{mul} operand3 t_mul operand4 |
{div} operand3 t_div operand4;

operand4 = {operand5} operand5 |
{power} operand4 t_power operand5;

operand5 = {operand6} operand6 |
{sin} t_sin t_open operand t_close |
{cos} t_cos t_open operand t_close |
{tan} t_tan t_open operand t_close |
{cotan} t_cotan t_open operand t_close |
{asin} t_asin t_open operand t_close |
{acos} t_acos t_open operand t_close |
{atan} t_atan t_open operand t_close |
{acotan} t_acotan t_open operand t_close |
{sqr} t_sqr t_open operand t_close |
{sqrt} t_sqrt t_open operand t_close |
{cub} t_cub t_open operand t_close |
{cubrt} t_cubrt t_open operand t_close |
{exp} t_exp t_open operand t_close |
{log} t_log t_open operand t_comma operand1 t_close |
{lg} t_lg t_open operand t_close |
{ln} t_ln t_open operand t_close;

operand6 = {operand7} operand7 |
{fact} operand7 t_fact;

operand7 = {term} term |
{bracket} t_open operand t_close;

term = {int} t_digits |
{num} t_num |
{var} t_var |
{pi} t_pi |
{e} t_e;


Đây là file đặc tả cú pháp biểu thức cho sablecc, sau khi có file này, gọi sablecc, thực chất là 1 tool, sẽ sinh ra toàn bộ code java cần thiết bao gồm: phân tích từ vựng, phân tích cú pháp, tạo cây cú pháp, việc duy nhất còn lại là viết phần sinh ra mã đích, cụ thể trong bài này là sinh ra biểu thức hậu tố và tính toán

với sablecc: sinh ra java
với antlr: sinh ra C++ hoặc java (tùy chọn)
với lex/yacc: sinh ra C thuần khiết

Toàn bộ project mình đặt ở đây, trong đó có file .bat để gọi sablecc (sablecc chỉ cần 1 file là sablecc.jar, có thể download ở nhiều chỗ), yêu cầu bạn có JRE, sau khi buid muốn chạy được thì thêm đường dẫn JRE\bin vào biến môi trường path. Project có sử dụng cả C++ và java, nên cũng tốt cho cả những bạn muốn tìm hiểu cách liên lạc C++ và java

http://j.1asphost.com/goldsoft2/download/code/expcalc.zip.2

nguyentuan2
29-09-2006, 11:10 AM
trong phần đặc tả này đáng lẽ phải mang phần operand 2 xuống gần dưới cùng, để làm cho toán tử 1 ngôi có độ ưu tiên cao nhất

bạn có thấy operand 3 khai báo phép chia và nhân, nằm dưới operand 1 khai báo phép + và -, điều đó nghĩa là phép chia/nhân có độ ưu tiên cao hơn phép cộng/trừ.

a4bk
29-09-2006, 12:38 PM
Cám ơn anh rất nhiều !
Mặc dù khống biết chút gì về C++, JaVa em cũng rất ấn tượng về chương trình của anh !
Em sẽ về cố công nghiên cứu ,nếu có gì không hiểu (chắc là rất nhiều ) em sẽ hỏi lại sau vậy !
Một lần nữa cảm ơn anh !