Tìm nghiệm phương trình bậc ba với sai số không quá 0.001

E có cái đề ngôn ngữ C như sau:
Nhập vào a b c d, giải pt bậc 3 với sai số k quá 0.001

Dưới đây là code của e:

#include<stdio.h>
#include<math.h>
#define PI 3.14159265359
void giaiPTBac3(int a,int b,int c,int d);
void giaiPTBac2(int a,int b,int c);
void giaiPTBac1(int a,int b);
int main(){
	int a,b,c,d;
	printf("Nhap vao 4 he so a b c d: ");
	scanf("%d%d%d%d",&a,&b,&c,&d);
	if(a == 0)
		if(b==0)
			giaiPTBac1(c,d);
		else
			giaiPTBac2(b,c,d);
	else
		giaiPTBac3(a,b,c,d);
	getch();
	return 0;
}

void giaiPTBac1(int a,int b){
	float x;
	if(a==0)
		if(b==0)
			printf("\n- Phuong trinh vo so nghiem\n");
		else
			printf("\n- Phuong trinh vo nghiem\n");
	else{
		x = (-(float)b/(2*a));
		printf("\n- Phuong trinh co 1 nghiem duy nhat\n");
		printf("x = %f",x);
	}
}

void giaiPTBac2(int a,int b,int c){
	float x1,x2,x,delta = pow(b,2) - (4*a*c);
	if(delta>0){
		x1 = (-(float)b+sqrt(delta))/(2*a);
		x2 = (-(float)b-sqrt(delta))/(2*a);
		printf("\n- Phuong trinh co 2 nghiem phan biet: \n");
		printf("x1 = %f\n", x1);
		printf("x2 = %f\n", x2);
	}else if(delta == 0){
		x = (-(float)b/(2*a));
		printf("\n- Phuong trinh co nghiem kep: \n");
		printf("x1 = x2 = %f\n", x);
	}else{
		printf("\n- Phuong trinh vo nghiem\n");
	}
}

void giaiPTBac3(int a,int b,int c,int d){
	float delta,k,x1,x2,x3,x;
	// Delta va K
	delta = pow(b,2) - (3*a*c);
	k = (9*a*b*c - 2*pow(b,3) - 27*pow(a,2)*d) / (2*sqrt(pow((fabs(delta)),3)));
	// Xet nghiem
	if(delta > 0){
		// Neu delta > 0
		if(fabs(k) <= 1){
			x1 = (2*sqrt(delta)*cos(((acos(k)/3)-((2*PI)/3)))-b) / (3*a);
			x2 = (2*sqrt(delta)*cos(((acos(k)/3)+((2*PI)/3)))-b) / (3*a);
			x3 = (2*sqrt(delta)*cos((acos(k)/3))-b) / (3*a);
			printf("\n- Phuong trinh co 3 nghiem: \n");
			printf("x1 = %f\n", x1);
			printf("x2 = %f\n", x2);
			printf("x3 = %f\n", x3);
		}else{
			x = ((sqrt(delta)*fabs(k))/(3*a*k))*(pow((fabs(k)+sqrt((pow(k,2)-1))),1.0/3)+pow((fabs(k)-sqrt((pow(k,2)-1))),1.0/3))-(b/3*a);
			printf("\n- Phuong trinh co 1 nghiem: \n");
			printf("x = %f\n", x);
		}
	}else if(delta == 0){
		x = (-b+(pow((pow(b,3)-27*pow(a,2)*d),1.0/3)))/(3*a);
		printf("\n- Phuong trinh co 1 nghiem boi: \n");
		printf("x = %f\n", x);
	}else{
		x = (sqrt(fabs(delta))/3*a)*(pow((k+sqrt((pow(k,2)+1))),1.0/3)+pow(-(k-sqrt((pow(k,2)+1))),1.0/3))-(b/3*a);
		printf("\n- Phuong trinh co 1 nghiem duy nhat: \n");
		printf("x = %f\n", x);
	}
}

E tìm được nghiệm rồi nhưng còn cái sai số k biết làm ntn xin ae chỉ giáo ạ :smile:

Cách tính Delta là tìm nghiệm chính xác luôn rồi. :V

Theo mình thì cái đề hướng dẫn tính xấp xỉ đó, dùng Newton’s method thử xem.

3 Likes

còn cái sai số 0.001 thì mình làm ntn ạ

Thì lấy \Delta x_n = x_{n} - x_{n-1}, nếu \Delta x_n < \epsilon = 0.001 thì dừng.

3 Likes

http://mathonline.wikidot.com/error-analysis-of-newton-s-method-for-approximating-roots

Đạo hàm bậc hai chia cho 2 lần đạo hàm bậc nhất là hệ số nhân hội tụ :slight_smile: tất nhiên là khi nó hội tụ.

3 Likes

xài bisection cũng được. Chọn x_1 = -1, x_2 = 1, cứ nhân 2 (x_1 = 2x_1, x_2 = 2x_2) cho tới khi f(x_1)f(x_2) < 0 thì chạy bisection :V :V cách này chậm hơn mà ko mất công chọn điểm khởi đầu như Newton’s method :V

https://amsi.org.au/ESA_Senior_Years/SeniorTopic3/3j/3j_2content_2.html

:V :V

2 Likes

Cái công thức thì e hiểu rồi nhưng mà trình bày ntn thì e chưa rõ :smile:

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?