PDA

View Full Version : chương trình tính nguyên hàm



neverstop
16-03-2005, 20:34
tôi đang muốn viết 1 chương trình tính nguyên hàm bằng C. mục đích ban đầu chỉ là tính những nguyên hàm đơn giản rồi từ từ phát triển lên sau. chương trình phải đảm bảo là in ra màn hình nguyên ham ở dạng "mà chúng ta hay viết trong vở". vd:
dx
tinh ---------
(x - 1)^2
1
thi chuong trinh phai in ra - -----
x - 1
một số dạng hàm đơn giản tôi đang bắt tay vào làm là: 1/(ax^2 + bx + c), (Ax + B)/(ax^2 + bx + c), (Ax + B)/sqrt(ax^2 + bx + c)
tôi đang gặp rắc rối ở chỗ trình bày kết quả ra màn hình ở dạng đẹp như trên vì chương trình rất rắc rối và khó nâng cấp.
hy vọng các bạn có hứng thú với chương trình này. bạn nào có ý tưởng xin cùng nhau chia sẻ. xin cảm ơn.

bete
16-03-2005, 22:56
Thân gửi neverstop: về phần in biểu thức toán thì tui nghĩ như vầy: giả sử mình biểu diễn được biểu thức toán bằng 1 cây nhị phân; và mình chỉ xét+,-,*,/,^, và √

Trước hết mình viết 1 hàm SắpChỗ(p): lấy vô 1 biểu thức p (dưới dạng cây nhị phân); và trả về p.rộng và p.cao

1) mình đang có biểu thức: T = T1+T2
=> Gọi SắpChỗ(T) => sẽ làm các bước sau:
Gọi SắpChỗ(T1) => T1.rộng, T1.cao
Gọi SắpChỗ(T2) => T2.rộng, T2.cao
T.rộng = T1.rộng + ChiềuRộng('+') + T2.rộng
T.cao = max(T1.cao, T2.cao)
          1
ví du: --- + 5
        234

2) mình đang có biểu thức: T = T1/T2
=> Gọi SắpChỗ(T) => sẽ làm các bước sau:
Gọi SắpChỗ(T1) => T1.rộng, T1.cao
Gọi SắpChỗ(T2) => T2.rộng, T2.cao
T.rộng = max(T1.rộng, T2.rộng)
T.cao = T1.cao + ChiềuCao('-') + T2.cao
          1
ví du: ---
        234

3) mình đang có biểu thức: T = T1^T2
=> Gọi SắpChỗ(T) => sẽ làm các bước sau:
Gọi SắpChỗ(T1) => T1.rộng, T1.cao
Gọi SắpChỗ(T2) => T2.rộng, T2.cao
T.rộng = T1.rộng + T2.rộng
T.cao = T1.cao + T2.cao
            1
           ---
           234
ví dụ: 56

4) mình đang có biểu thức: T = T1√T2
=> Gọi SắpChỗ(T) => sẽ làm các bước sau:
Gọi SắpChỗ(T1) => T1.rộng, T1.cao
Gọi SắpChỗ(T2) => T2.rộng, T2.cao
T.rộng = T1.rộng + ChiềuRộng('√') + T2.rộng
T.cao = T1.cao + ChiềuCao('_') + T2.cao
        2 ___         2___
ví dụ: √345 hoặc V345

Kế đến mình viết 1 hàm In(p, cột, dòng): lấy vô 1 biểu thức p (dưới dạng cây nhị phân) và tọa độ tuyệt đối cột, dòng

1) mình đang có biểu thức: T = T1+T2
=> Gọi In(T, cột, dòng) => sẽ làm các bước sau:
Gọi In(T1, cột, dòng + (T.cao-T1.cao)/2)
gotoxy(cột + T1.rộng, dòng + T.cao/2)
in '+'
Gọi In(T2, cột + T1.rộng + ChiềuRộng('+'), dòng + (T.cao-T2.cao)/2)

2) mình đang có biểu thức: T = T1/T2
=> Gọi In(T, cột, dòng) => sẽ làm các bước sau:
Gọi In(T1, cột + (T.rộng-T1.rộng)/2, dòng)
gotoxy(cột, dòng + T1.cao)
in '-' (số lần lặp là T.rộng)
Gọi In(T2, cột + (T.rộng-T2.rộng)/2, dòng + T1.cao + ChiềuCao('---'))

3) mình đang có biểu thức: T = T1^T2
=> Gọi In(T, cột, dòng) => sẽ làm các bước sau:
Gọi In(T2, cột + T1.rộng, dòng)
Gọi In(T1, cột, dòng + T2.cao)

4) mình đang có biểu thức: T = T1√T2
=> Gọi In(T, cột, dòng) => sẽ làm các bước sau:
Gọi In(T1, cột, dòng)
gotoxy(cột+ T1.rộng + ChiềuRộng('√'), dòng + T1.cao)
in '_' (số lần lặp là T2.rộng)
gotoxy(cột+ T1.rộng, dòng + T1.cao + ChiềuCao('___'))
in '√'
Gọi In(T2, cột + T1.rộng + ChiềuRộng('√'), dòng + T1.cao + ChiềuCao('___'))

---------------------------------------

Có thể sửa lại 1 chút (để nếu cần in 1 biểu thức nhiều lần thì sẽ lợi hơn):

1) mình đang có biểu thức: T = T1+T2
=> Gọi SắpChỗ(T) => sẽ làm các bước sau:
Gọi SắpChỗ(T1) => T1.rộng, T1.cao
Gọi SắpChỗ(T2) => T2.rộng, T2.cao
T.rộng = T1.rộng + ChiềuRộng('+') + T2.rộng
T.cao = max(T1.cao, T2.cao)
T1.dx = 0
T1.dy = (T.cao-T1.cao)/2
T2.dx = T1.rộng + ChiềuRộng('+')
T2.dy = (T.cao-T2.cao)/2

2) mình đang có biểu thức: T = T1/T2
=> Gọi SắpChỗ(T) => sẽ làm các bước sau:
Gọi SắpChỗ(T1) => T1.rộng, T1.cao
Gọi SắpChỗ(T2) => T2.rộng, T2.cao
T.rộng = max(T1.rộng, T2.rộng)
T.cao = T1.cao + ChiềuCao('-') + T2.cao
T1.dx = (T.rộng-T1.rộng)/2
T1.dy = 0
T2.dx = (T.rộng-T1.rộng)/2
T2.dy = T1.cao + ChiềuCao('---')

3) mình đang có biểu thức: T = T1^T2
=> Gọi SắpChỗ(T) => sẽ làm các bước sau:
Gọi SắpChỗ(T1) => T1.rộng, T1.cao
Gọi SắpChỗ(T2) => T2.rộng, T2.cao
T.rộng = T1.rộng + T2.rộng
T.cao = T1.cao + T2.cao
T1.dx = 0
T1.dy = T2.cao
T2.dx = T1.rộng
T2.dy = 0

4) mình đang có biểu thức: T = T1√T2
=> Gọi SắpChỗ(T) => sẽ làm các bước sau:
Gọi SắpChỗ(T1) => T1.rộng, T1.cao
Gọi SắpChỗ(T2) => T2.rộng, T2.cao
T.rộng = T1.rộng + ChiềuRộng('√') + T2.rộng
T.cao = T1.cao + ChiềuCao('_') + T2.cao
T1.dx = 0
T1.dy = 0
T2.dx = T1.rộng + ChiềuRộng('√')
T2.dy = T1.cao + ChiềuCao('___')

Kế đến mình viết 1 hàm In(p, cột, dòng): lấy vô 1 biểu thức p (dưới dạng cây nhị phân) và tọa độ tuyệt đối cột, dòng

1) mình đang có biểu thức: T = T1+T2
=> Gọi In(T, cột, dòng) => sẽ làm các bước sau:
Gọi In(T1, cột /*+ T1.dx*/, dòng + T1.dy)
gotoxy(cột + T1.rộng, dòng + T.cao/2)
in '+'
Gọi In(T2, cột + T2.dx, dòng + T2.dy)

2) mình đang có biểu thức: T = T1/T2
=> Gọi In(T, cột, dòng) => sẽ làm các bước sau:
Gọi In(T1, cột + T1.dx, dòng /*+ T1.dy*/)
gotoxy(cột, dòng + T1.cao)
in '-' (số lần lặp là T.rộng)
Gọi In(T2, cột + T2.dx, dòng + T2.dy)

3) mình đang có biểu thức: T = T1^T2
=> Gọi In(T, cột, dòng) => sẽ làm các bước sau:
Gọi In(T2, cột + T2.dx, dòng /*+ T2.dy*/)
Gọi In(T1, cột /*+ T1.dx*/, dòng + T1.dy)

4) mình đang có biểu thức: T = T1√T2
=> Gọi In(T, cột, dòng) => sẽ làm các bước sau:
Gọi In(T1, cột /*+ T1.dx*/, dòng /*+ T1.dy*/)
gotoxy(cột+ T1.rộng + ChiềuRộng('√'), dòng + T1.cao)
in '_' (số lần lặp là T2.rộng)
gotoxy(cột+ T1.rộng, dòng + T1.cao + ChiềuCao('___'))
in '√'
Gọi In(T2, cột + T2.dx, dòng + T2.dy)

Vài điểm cần lưu ý:
Trường hợp căn bản nhứt: T = 1 số =>.........
Có thể mở rộng ra cho các hàm lượng giác, lô-ga-rit,.....
Chế độ văn bản & đồ họa => cách làm tương tự nhau

*** Nhưng phải tìm được nguyên hàm thì mới có kết quả để in:)

(có gì sai sót xin các bạn chỉ giúp, cám ơn rất nhiều)

-thân

neverstop
18-03-2005, 19:08
cảm ơn bete đã cho ý kiến.
tôi thấy cách giải quyết của bạn áp dụng cho cả trường hợp tổng quát được. nhưng bạn chưa hiểu rõ ý của tôi. vấn đề không phải là in được hay không nguyên hàm của 1 hàm số mà là in nó ở dạng như thế nào. tôi muốn dạng in ra phải thật đẹp, giống như trình bày trong sách vở.

1
vd: với hàm số --------------
ax^2 + bx + c
thì nguyên hàm của nó có dạng (tôi tạm ký hiệu / là căn thức)
2
- -------- + C nếu delta = 0
2ax + b
2 2ax + b
- -------arctg--------- + C nếu delta < 0
/(-delta) /(-delta)
1 2ax + b - /(delta)
- -------ln----------------- + C nếu delta > 0
/(delta) 2ax + b - /(delta)muốn biểu thức có dạng đẹp thì phải chú ý ít nhất là những điểm sau:
- delta = e^2*f thì phải đưa e^2 ra ngoài dấu căn
- 1*x thì phải viết là x
- phân số thì các hệ số phải được tối giản
- tử số và mẫu sỗ của phân số phải được viết căn lề vào chính giữa của phân số
hiện giờ tôi mới chỉ hoàn thành tích phân ở trên thôi, chương trình đã in ra được đúng dạng yêu cầu nhưng chương trình rất rắc rối và khó áp dụng cho những trường hợp khác. lần sau tôi sẽ post cả chương trình lên cho các bạn xem xét.
mong các bạn góp ý kiến thêm.

bete
18-03-2005, 19:56
Thân gửi never stop:

1) delta = e^2*f thì phải đưa e^2 ra ngoài dấu căn

=> bạn có thể nói rõ hơn 1 chút ?(tui không thấy dấu căn ở trong "e^2*f")
Có phải bạn muốn nói √((e²)f) = e√f ?

2) 1*x thì phải viết là x
3) phân số thì các hệ số phải được tối giản

=> tui nghĩ có lẽ nên tách cái này ra khỏi phần in ấn mà để vô phần tính toán. Như vậy nếu mình có 1 biểu thức được in ở nhiều nơi thì sẽ lợi. Hơn nữa khi trình bày thì có thể giả định là biểu thức đã gọn rồi, chỉ sắp vô dòng nào, cột nào cho đẹp thôi. Nếu mình biểu diễn diễn biểu thức toán bằng cây nhị phân thì có thể viết 1 hàm/thủ tục TốiGiản(T) => xét các trường hợp mình nghĩ tới. Ví dụ:

a) T=T1+T2: nếu T1 là hằng số 0 thì T=T2 (nếu T2 cũng là hằng số 0 nữa thì T=hằng số 0), nếu T2 là hằng số 0 thì .............

b) T=T1-T2: nếu T2 là hằng số 0 thì T=T1

c) T=T1-T2: nếu T1=T2 thì T=hằng số 0. Để xác định T1=T2 thì hơi mất công 1 chút (phải gọi đệ qui). Ví dụ nếu T1 = x+y và T2 = (1*y) + (x/1) thì T1 bằng T2

d) T=T1*T2: nếu T1 là 1 thì....., nếu T2 là 1 thì .............

e) T=T2 \ T1 (ví dụ: 3 \ 8=> căn bậc 3 của 8): nếu T1 là hằng số a và T2=T3^a thì T=T3

f) T=T1^T2: nếu T1 là hằng số a và T2=a\T3 (căn bậc a của T3) thì T=T3

g) T=log(T1,T2) (log cơ số T1 của T2): nếu T1 là hằng số a và T2=T3^a thì T=T3

....(còn vô số trường hợp khác mình phải nghĩ tới nữa; có thể bắt đầu bằng vài trường hợp rồi thêm vô từ từ)

4) tử số và mẫu số của phân số phải được viết căn lề vào chính giữa của phân số

=> mình sẽ làm được chuyện này qua (T.rộng-T1.rộng)/2

1 điểm nhỏ: x*y có nên in là xy hay không ? nói chung là nên, nhưng mình phải coi chừng lỡ như mình có 1 biến tên là xy => sẽ bị lộn

1 điểm nhỏ nữa: để xác định T1 có bằng T2 hay không, mình có thể viết 1 hàm CóBằngNhau(T1, T2) và xét các trường hợp:

a) T1=hằng số a và T2= hằng số b và a bằng b thì ...

b) nếu TốiGiản(T1)=TốiGiản(T2) thì.....

c) T1=T3+T4 và T2=T5+T6: nếu TốiGiản(T3)=TốiGiản(T5) và TốiGiản(T4)=TốiGiản(T6) thì.....; nếu TốiGiản(T3)=TốiGiản(T6) và TốiGiản(T4)=TốiGiản(T5) thì.....

....(còn vô số trường hợp khác mình phải nghĩ tới nữa; có thể bắt đầu bằng vài trường hợp rồi thêm vô từ từ)

(vài ý thô thiển; có gì sai sót xin các bạn chỉ giúp, cám ơn rất nhiều)

-thân

neverstop
20-03-2005, 19:06
tôi thấy cách tiếp cận bài toán của bete xa với thực tế quá, vì như thế giồng như trên lý thuyết. khi bắt tay vào làm bài thì có rất nhiều trường hợp về trình bày có thể xảy ra, cho nên chương trình rất là phức tạp.
bạn thử xem bài làm của tôi viết bằng C, chỉ tính nguyên hàm cho hàm số dạng 1/(ax^2 + bx + c) thôi.
tôi muốn thảo luận 1 cách chi tiết về chương trình viết ra để có thể tối ưu nó và nâng cấp nó cho những hàm khác.
mong các bạn cùng xem và góp ý kiến.

Mach2
20-03-2005, 21:27
tôi thấy câu trả lời của bete là khá thỏa đáng rồi đó chứ. Thật ra vấn đề của bạn chỉ có thể giải quyết được trong trường hợp tổng quát (theo như bạn muốn) nếu như bạn xây dựng được một phương thức có thể đơn giản một biểu thức hàm bất kỳ (hay ít nhất trong một dạng nào đó) -> thế thì bete đã đưa ra một vài gợi ý tốt rồi.
Tôi có lướt sơ code của bạn (trong vài giây) thì thấy bạn dùng "if then else" để quét trường hợp. Như thế thì đúng là bạn ko thể nào áp dụng "1 code cho nhiều trường hợp" như bạn nói được.

neverstop
27-03-2005, 17:25
hiện giờ tôi chỉ muốn làm chương trình để tính các nguyên hàm rất đơn giản thôi, một số nguyên hàm mà ta đã biết (như đã viết ở trên). hơn nữa mục đích của tôi chỉ là phục vụ cho việc học tập, nên các hệ số đều là các số nguyên (thường gặp trong nhà trường). tôi không có ham muốn viết một chương trình toàn năng, có thể tính được hết các nguyên hàm.
chương trình tôi viết kia vì xử lý với số nguyên và có dạng in ra màn hình đẹp cho nên phải quét rất nhiều trường hợp. cho nên nó khó có thể áp dụng vào tính những nguyên hàm đơn giản khác. tôi muốn các bạn góp ý cho chỗ nào chưa được trong phần xử lý với các số nguyên trong việc in ấn ra màn hình.
cảm ơn các bạn.

xinh_gai
12-04-2005, 13:21
Newbie cũng vừa viết được 1 bài toán tính hệ phuơng trình n ẩn (hoặc giải hệ tuyến tính) ,không biết có được chút gì các bác không

bete
21-05-2005, 12:25
Thân gửi neverstop: chức năng attach (upload) file của diễn đàn không xài được
=> bạn có hứng thú debug thì cho tui địa chỉ email, tui sẽ gửi coi thử

-thân