Си методы нахождения корня функции
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
double fc1(double x){
return (3*powf(log(x), 2) + 6 * log(x) - 5);
}
double fc2(double x){
return (0.6 * powf(3, x) - 2.3 * x - 3);
}
double fc1pr(double x){
return (6*log(x) / x + 6./x);
}
double fc2pr(double x){
return (0.659167 * pow(3, x) - 2.3);
}
double fc3(double x){
return ( (-0.1667) * (3*powf(log(x), 2) + 6 * log(x) - 5) + x);
}
double fc4(double x){
return ((-0.06453) * (0.6 * powf(3, x) - 2.3 * x - 3) + x);
}
double dihot (double a,double b,double f(double x), double epsil){
double x=0;
//if (fabs(f((a + b)/2.0)) < 1){
while (fabs(a-b)>epsil){
x = (a+b)/2.0;
if (f(a)*f(x) > 0.0){
a = x;
}
else{
b = x;
}
}
//}
return x;
}
double newthon(double a, double b, double f1(double x), double f2(double x), double epsil){
double x = (a +b) / 2.0;
while(fabs(f1(x)/f2(x))>=epsil){
x -= f1(x)/f2(x);
}
return x;
}
double iter (double a, double b, double f(double), double epsil){
double x = (a+b)/2.0;
while (fabs(x - f(x))>=epsil){
x = f(x);
}
return x;
}
int main(void) {
double epsil = 1.0;
while (1 + epsil/2 > 1){
epsil /=2;
}
printf("Машинное эпсилон = %.16e\n", epsil);
printf("Функция(номер 7) 3*(ln(x))^2 + 6*ln(x) - 5\n");
printf("Метод Дихотомии \t%f\n", dihot(1.0,3.0,fc1,epsil));
printf("Метод Итераций \t%f\n", iter(1.0,3.0,fc3,epsil));
printf("Метод Ньютона \t%.7f\n", newthon(1.0,3.0,fc1,fc1pr,epsil));
printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
printf("Функция(номер 8) 0.6*3^x - 2.3*x - 3\n");
printf("Метод Дихотомии \t%.10f\n", dihot(2.0,3.0,fc2,epsil));
printf("Метод Итераций \t%.10f\n", iter(2.0,3.0,fc4,epsil));
printf("Метод Ньютона \t%.10f", newthon(2.0,3.0,fc2,fc2pr,epsil));
return 0;
}
Задача состоит в нахождении корня уравнения по 3 методам, fc3 fc4 - функции для метода итераций для функций fc1 fc2 соответственно, f1pr f2pr - производные функций f1 f2. Есть заккомментированный вывод, он не работает, при этом не понимаю почему, вот функции
Ответы (1 шт):
Просто работать возле машинной точности — дело очень, гм... нездоровое.
Добавим отладочный вывод и посмотрим
while (fabs(a-b)>epsil){
printf("a = %lf, b = %lf, eps = %lg\n",a,b,b-a);
x = (a+b)/2.0;
его результаты зацикливаются на
a = 2.419982, b = 2.419982, eps = 4.44089e-16
Просто слишком задранная точность.
Для итераций отладочный вывод дает
x = 2.419982, f(x) = 2.419982 eps = 3.20428e-08
x = 2.419982, f(x) = 2.419982 eps = -7.39745e-08
x = 2.419982, f(x) = 2.419982 eps = 2.58194e-08
x = 2.419982, f(x) = 2.419982 eps = 2.96515e-08
x = 2.419982, f(x) = 2.419982 eps = 3.40523e-08
x = 2.419982, f(x) = 2.419982 eps = -7.16668e-08
x = 2.419982, f(x) = 2.419982 eps = 2.84696e-08
x = 2.419982, f(x) = 2.419982 eps = 3.2695e-08
.....
Ньютона оставляю вам в качестве самостоятельной работы :)
P.S. Отладочный вывод — отличное средство для понимания того, что происходит. Если бы профессором был я :), я бы этому учил, наверное, самому первому. Этот метод успешно работал, когда еще никаких отладчиков не было...
P.P.S. Рекомендовал бы для методов итерации и Ньютона просто на бумажке и с калькулятором прикинуть точности вычислений.