banner

[Rule] Rules  [Home] Main Forum  [Portal] Portal  
[Members] Member Listing  [Statistics] Statistics  [Search] Search  [Reading Room] Reading Room 
[Register] Register  
[Login] Loginhttp  | https  ]
 
Forum Index Thảo luận hệ điều hành Windows Hỏi về C++ ??  XML
  [Programming]   Hỏi về C++ ?? 26/09/2008 22:54:56 (+0700) | #1 | 153049
netbusxx
Member

[Minus]    0    [Plus]
Joined: 21/06/2008 00:59:17
Messages: 35
Offline
[Profile] [PM]
Mình mới học C++, mình có đoạn mã sau, không hiểu là sai đoạn nào, các bạn xem giùm mình mới nha :

Code:
/*
  Doc vao so nguyen duong x va uoc luong gia tri gan dung cua e^x bang cong thuc:
		  e^x = 1 + x + x^2/2! + x^3/3! + x^4/4! + ......
		  */
#include <iostream>
#include <conio.h>
#include <math.h>

using namespace std;

int giai_thua(int a){		
	if (a==0 || a==1)	return 1;
	else	
		return a*giai_thua(a-1);
}
main(){
	int x;
	float t=1,kq=0,epxilon=0.000001;		
	cout<<"\nNhap vao so nguyen duong x = ";
	cin>>x;
	int j=0;
	while(t>=epxilon){	
		t = pow(x,j)/giai_thua(j);		
		kq = kq + t;	
		j++;
	}
	cout<<"Ket qua e^"<<x<<" =  "<<kq;

	getch ();
}


Mình thay x = 1,2,3 thì kết quả đúng, nhưng với x >= 4 thì kết quả lại sai. Có thể thuật toan scura mình sai, nhưng mình lại không bít được sai chỗ nào . Rất mong các bạn hộ mình với
[Up] [Print Copy]
  [Question]   Re: Hỏi về C++ ?? 26/09/2008 23:57:45 (+0700) | #2 | 153051
FaL
Moderator

Joined: 14/04/2006 09:31:18
Messages: 1232
Offline
[Profile] [PM]
Bồ xem lại giới hạn của kiểu int. Với x = 4 thì đến vòng lặp thứ bao nhiêu vượt quá giới hạn của kiểu int?
Hãy giữ một trái tim nóng và một cái đầu lạnh
[Up] [Print Copy]
  [Question]   Re: Hỏi về C++ ?? 26/09/2008 23:59:36 (+0700) | #3 | 153052
[Avatar]
4hfoo
Elite Member

[Minus]    0    [Plus]
Joined: 29/01/2007 01:50:20
Messages: 115
Offline
[Profile] [PM]
Chương trình bạn bị lỗi tràn số nguyên (integer overflow) phần tính giai_thua().
Ban để kiểu int thì hàm tính giai thừa không thể tính n! với n lớn được.
Một cách để sửa bạn có thể đổi int thành double.
Và cũng nên đổi float thành double để khoảng giá trị chứa sẽ lớn hơn.

Chú ý, đổi thành double tăng khoảng tính n!, nhưng nếu n lớn quá thì cũng vẫn bị tràn và sẽ dẫn đến kq sai.

Thân
[Up] [Print Copy]
  [Question]   Re: Hỏi về C++ ?? 28/09/2008 09:32:43 (+0700) | #4 | 153196
netbusxx
Member

[Minus]    0    [Plus]
Joined: 21/06/2008 00:59:17
Messages: 35
Offline
[Profile] [PM]
Minh cảm ơn nha,đúng là dùng kiểu double thì đáp số đúng . Thanks.......
[Up] [Print Copy]
  [Question]   Re: Hỏi về C++ ?? 28/09/2008 10:19:16 (+0700) | #5 | 153198
[Avatar]
khatkhaotrithuc
Member

[Minus]    0    [Plus]
Joined: 20/03/2008 00:45:13
Messages: 38
Offline
[Profile] [PM]
Xin chào @netbusxx

Mình có test thì thấy với kiểu int, thì hàm giai_thua(int n) chỉ tính được các số từ 0->7 thôi!!.

Vì vậy, để tính giaithua cho các số lơn hơn bạn phải khai báo kiểu lớn hơn.

Nhưng điều quan trọng ở đây là với kiểu lớn hơn như thế, thì khi tính giaithua cho một con số quá lơn thì hàm giaithua bằng đệ qui sẽ không tối ưu(chương trình chạy chậm vì tốn thời gian gọi hàm đệ qui).

Ta dùng vòng lặp sẽ tối ưu hơn ban ơi!!:

float giai_thua(float n){
float gt=1; int i;
if(n==0 ||n==1) return(gt);
i=2;
while(i<=n){
gt*=i;
++i;
}
return(gt);
}
[Up] [Print Copy]
  [Question]   Re: Hỏi về C++ ?? 29/09/2008 02:05:12 (+0700) | #6 | 153275
FaL
Moderator

Joined: 14/04/2006 09:31:18
Messages: 1232
Offline
[Profile] [PM]

khatkhaotrithuc wrote:
Xin chào @netbusxx

Mình có test thì thấy với kiểu int, thì hàm giai_thua(int n) chỉ tính được các số từ 0->7 thôi!!.

Vì vậy, để tính giaithua cho các số lơn hơn bạn phải khai báo kiểu lớn hơn.

Nhưng điều quan trọng ở đây là với kiểu lớn hơn như thế, thì khi tính giaithua cho một con số quá lơn thì hàm giaithua bằng đệ qui sẽ không tối ưu(chương trình chạy chậm vì tốn thời gian gọi hàm đệ qui).

Ta dùng vòng lặp sẽ tối ưu hơn ban ơi!!:

float giai_thua(float n){
float gt=1; int i;
if(n==0 ||n==1) return(gt);
i=2;
while(i<=n){
gt*=i;
++i;
}
return(gt);


Còn tối ưu được không bồ? smilie
Như thế này là mỗi lần tính số hạng nào đó của dãy phải tính lại cả giaithua(n), tính lại cả x^n... ?
Hãy giữ một trái tim nóng và một cái đầu lạnh
[Up] [Print Copy]
  [Question]   Re: Hỏi về C++ ?? 29/09/2008 13:07:05 (+0700) | #7 | 153327
netbusxx
Member

[Minus]    0    [Plus]
Joined: 21/06/2008 00:59:17
Messages: 35
Offline
[Profile] [PM]

khatkhaotrithuc wrote:
Xin chào @netbusxx

Mình có test thì thấy với kiểu int, thì hàm giai_thua(int n) chỉ tính được các số từ 0->7 thôi!!.

Vì vậy, để tính giaithua cho các số lơn hơn bạn phải khai báo kiểu lớn hơn.

Nhưng điều quan trọng ở đây là với kiểu lớn hơn như thế, thì khi tính giaithua cho một con số quá lơn thì hàm giaithua bằng đệ qui sẽ không tối ưu(chương trình chạy chậm vì tốn thời gian gọi hàm đệ qui).

Ta dùng vòng lặp sẽ tối ưu hơn ban ơi!!:

float giai_thua(float n){
float gt=1; int i;
if(n==0 ||n==1) return(gt);
i=2;
while(i<=n){
gt*=i;
++i;
}
return(gt);


Mình cảm ơn bạn đã đóng góp ý kiến cho minh, nhưng cho mình hỏi nữa là làm sao để bít được hàm đệ qui chạy chậm hơn hàm của bạn không ạ, vì mình dùng cả hai cách thì đều thấy "nhanh" cả, chẳng biết nhận ra bằng cách nào. Mình cũng thấy người khác bảo dùng đệ qui là không tối ưu, 1 số bài toán lại chỉ có thể giải được bằng đệ qui.
[Up] [Print Copy]
  [Question]   Re: Hỏi về C++ ?? 29/09/2008 13:26:04 (+0700) | #8 | 153328
[Avatar]
K4i
Moderator

Joined: 18/04/2006 09:32:13
Messages: 635
Location: Underground
Offline
[Profile] [PM]
@netbusxx: để thấy được độ nhanh hay chậm của 2 đoạn code một cách trực quan và rõ ràng nhất thì hãy thử tính khoảng (10^9)! xem. Nhưng với 2 đoạn code trên thì điều này là không thể smilie, bạn chắc hiểu tại sao.

Còn một cách khác là dùng hàm tính thời gian trong C/C++ => cái này thì tự tìm hiểu. Một số IDE cho C/C++ version mới (như Code::Blocks) khi compile đều chèn thêm thời gian thực hiện chương trình đó. Bạn có thể thử nếu như không biết code hàm tính thời gian thế nào.
Sống là để không chết chứ không phải để trở thành anh hùng
[Up] [Print Copy]
  [Question]   Re: Hỏi về C++ ?? 30/09/2008 11:00:11 (+0700) | #9 | 153391
netbusxx
Member

[Minus]    0    [Plus]
Joined: 21/06/2008 00:59:17
Messages: 35
Offline
[Profile] [PM]
Các bạn lại cho mình hỏi bài sau với nha: Nhập vào 1 số có số chữ số >= 15. Kiểm tra tính chia hết của số này với 7. Mình biết dấu hiệu chia hết của 7, nhưng không biết áp dụng thế nào với 1 số có số chữ số >= 15 cả.
[Up] [Print Copy]
  [Question]   Re: Hỏi về C++ ?? 30/09/2008 11:07:20 (+0700) | #10 | 153392
[Avatar]
K4i
Moderator

Joined: 18/04/2006 09:32:13
Messages: 635
Location: Underground
Offline
[Profile] [PM]

netbusxx wrote:
Các bạn lại cho mình hỏi bài sau với nha: Nhập vào 1 số có số chữ số >= 15. Kiểm tra tính chia hết của số này với 7. Mình biết dấu hiệu chia hết của 7, nhưng không biết áp dụng thế nào với 1 số có số chữ số >= 15 cả. 


Vấn đề mới, tạo topic mới nhé
Sống là để không chết chứ không phải để trở thành anh hùng
[Up] [Print Copy]
  [Question]   Re: Hỏi về C++ ?? 30/09/2008 11:13:53 (+0700) | #11 | 153394
[Avatar]
khatkhaotrithuc
Member

[Minus]    0    [Plus]
Joined: 20/03/2008 00:45:13
Messages: 38
Offline
[Profile] [PM]
 

Mình cảm ơn bạn đã đóng góp ý kiến cho minh, nhưng cho mình hỏi nữa là làm sao để bít được hàm đệ qui chạy chậm hơn hàm của bạn không ạ, vì mình dùng cả hai cách thì đều thấy "nhanh" cả, chẳng biết nhận ra bằng cách nào. Mình cũng thấy người khác bảo dùng đệ qui là không tối ưu, 1 số bài toán lại chỉ có thể giải được bằng đệ qui. 

Chào bạn, hàm đệ qui chạy chậm hơn là tại vì:

1. Khi tính giai thừa của một số thì trước tiên CPU lưu địa chỉ trở về, sau đó gọi hàm đệ qui tính giai_thua(), và sau khi thực hiện xong thì chương trình sẽ thực hiện tiếp dòng lệnh ở địa chỉ trở về của hàm gọi nó. Điều này làm "tốn thời gian chuyển ngữ cảnh không cần thiết"-> khắc phục: dùng macro!!.

2. Bản thân đệ qui tính giai_thua() lại gọi lại chính nó, khi đó đối với những con số quá lớn(tỉ chẳng hạng) thì khi các hàm gọi lồng nhau nhiều cấp thì càng chiếm dụng nhiều bộ nhớ.(lập trình cho điện thoại di động kiểu này là "toi").
->khắc phục: nên dùng vòng lặp và sử dụng đệ qui khi thực sự cần thiết!!.

1, 2-> bài toán của chúng ta không được tối ưu.

"vì mình dùng cả hai cách thì đều thấy "nhanh" cả"
Như bạn đã biết, CPU tính toán với tốc độ cực kỳ nhanh, vì vậy những lần test với những con số tương đối nhỏ như vậy, bằng cảm nhận thông thường thì không tài nào phân biệt rỏ đâu bạn!!!

Thân chào!! smilie




[Up] [Print Copy]
  [Question]   Re: Hỏi về C++ ?? 30/09/2008 11:43:36 (+0700) | #12 | 153397
[Avatar]
khatkhaotrithuc
Member

[Minus]    0    [Plus]
Joined: 20/03/2008 00:45:13
Messages: 38
Offline
[Profile] [PM]

FaL wrote:

khatkhaotrithuc wrote:
Xin chào @netbusxx

Mình có test thì thấy với kiểu int, thì hàm giai_thua(int n) chỉ tính được các số từ 0->7 thôi!!.

Vì vậy, để tính giaithua cho các số lơn hơn bạn phải khai báo kiểu lớn hơn.

Nhưng điều quan trọng ở đây là với kiểu lớn hơn như thế, thì khi tính giaithua cho một con số quá lơn thì hàm giaithua bằng đệ qui sẽ không tối ưu(chương trình chạy chậm vì tốn thời gian gọi hàm đệ qui).

Ta dùng vòng lặp sẽ tối ưu hơn ban ơi!!:

float giai_thua(float n){
float gt=1; int i;
if(n==0 ||n==1) return(gt);
i=2;
while(i<=n){
gt*=i;
++i;
}
return(gt);


Còn tối ưu được không bồ? smilie
Như thế này là mỗi lần tính số hạng nào đó của dãy phải tính lại cả giaithua(n), tính lại cả x^n... ? 


Em xin chào bác!!

Với bài tập của bạn, em chỉ nghi được một vài điểm cần được tối ưu bởi lập trình viên:
1. Viết lại hàm giai_thua bằng vòng lặp.
2. kq+=t;
3.++j;

Còn hàm pow(x,j)-> em nghĩ tối ưu sẳn cho chúng ta!.

Với hàm giai_thua em nghĩ nên dùng macro để không tốn "thời gian chuyển ngữ cảnh không cần thiết".

Tới đây em hết "bít", rất mong được sự chỉ giáo từ bác. Xin chân thành cảm ơn!! smilie
[Up] [Print Copy]
  [Question]   Re: Hỏi về C++ ?? 30/09/2008 11:52:33 (+0700) | #13 | 153399
seraphpl
Member

[Minus]    0    [Plus]
Joined: 04/12/2006 19:52:12
Messages: 97
Location: xxx
Offline
[Profile] [PM] [WWW] [Yahoo!] [MSN] [ICQ]

khatkhaotrithuc wrote:


Em xin chào bác!!

Với bài tập của bạn, em chỉ nghi được một vài điểm cần được tối ưu bởi lập trình viên:
1. Viết lại hàm giai_thua bằng vòng lặp.
2. kq+=t;
3.++j;

Còn hàm pow(x,j)-> em nghĩ tối ưu sẳn cho chúng ta!.

Với hàm giai_thua em nghĩ nên dùng macro để không tốn "thời gian chuyển ngữ cảnh không cần thiết".

Tới đây em hết "bít", rất mong được sự chỉ giáo từ bác. Xin chân thành cảm ơn!! smilie  

j=1
giai_thua=1
pow=1
kq=0
khi t>=epxelon
1. t = pow/giai_thua
2. kq=kq+t
3. pow = pow*x
4. giai_thua = giai_thua*j
5. j++
[Up] [Print Copy]
  [Question]   Re: Hỏi về C++ ?? 30/09/2008 12:30:09 (+0700) | #14 | 153403
[Avatar]
khatkhaotrithuc
Member

[Minus]    0    [Plus]
Joined: 20/03/2008 00:45:13
Messages: 38
Offline
[Profile] [PM]
@seraphpl

Chào seraphpl giải thuật của bạn là tối ưu số 1; rất vui khi được học hỏi!! smilie
[Up] [Print Copy]
  [Question]   Re: Hỏi về C++ ?? 30/09/2008 13:08:15 (+0700) | #15 | 153407
Reversing...
Member

[Minus]    0    [Plus]
Joined: 31/12/2007 06:28:04
Messages: 117
Location: -1.-1.-1.-1
Offline
[Profile] [PM] [Yahoo!]
Có thể dùng đệ quy để giải bài này.


Code:
// r - kết quả.
f(int n, double t, double &r)
{
      if ( t < epsilon) return r;
      f( n + 1, x*x/n/(n+1), r + t/n );
}
[Up] [Print Copy]
[digg] [delicious] [google] [yahoo] [technorati] [reddit] [stumbleupon]
Go to: 
 Users currently in here 
1 Anonymous

Powered by JForum - Extended by HVAOnline
 hvaonline.net  |  hvaforum.net  |  hvazone.net  |  hvanews.net  |  vnhacker.org
1999 - 2013 © v2012|0504|218|