Obliczanie pierwiastka równania nieliniowego - Iteracja prosta - Błędny wynik

0

Witam,
Mam problem z działaniem prostego programu obliczającego pierwiastek funkcji nieliniowej z wykorzystaniem metody iteracji prostej.
Funkcja jest następująca:
Bez tytułu.png
f8e9bd257d.png

a kod programu wygląda tak:

#include "stdafx.h"
#include "stdio.h"
#include "conio.h"
#include "math.h"

double x1;                 // x1 - punkt poczatkowy, od ktorego rozpoczynamy obliczenia
double x2;                 // x2 - poszukiwany pierwiastek
double blad=0.001;        // blad - blad przyblizenia
double wynik;             // wynik - zmienna pomocnicza, jej wynik jest brany do warunku petli

double funkcja(double x) // wartosc przeksztalconej funkcji
{
	return pow(x,2)+3/x ;  // Przeksztalcona funkcja poczatkowa
}
int main()
{
	x1=1; // punkt poczatkowy
	do
	{
		x2=funkcja(x1); // wartosc pierwiastka
		wynik=fabs(x2-x1); // blad, petla jest wykonywana dopoki jest on wiekszy od bledu przyblizenia
		x1=x2; // nowa wartosc punktu startowego
	}
	while(wynik>=blad);
	printf("Poszukiwany pierwiastek to x= %lf",x2);

	getch();
	return 0;
} 

Wynik:
00bc9e09dd.png

Jak widać na wykresie jest pierwiastek w punkcie około -1, a wynik jest zupełnie inny.
Czy wie ktoś w czym leży problem?
Proszę o pomoc :)
Pozdrawiam

0

Może mnie oświecisz jakim cudem z: x3-x2+3 zrobiło się: x2+3/x ?

0

x3-x2+3=0
x2=x3+3 /x
x=x2+3/x

Przy czym równanie x=x2+3/x jest równaniem równoważnym otrzymanym po zastąpieniu równania wyjściowego f(x)=0 => x=q(x).

0

Ponadto po podstawieniu "na kartce" liczby początkowej, oraz kolejnych powstajcych liczby w pętli, różnica pierwiastków x1 i x2 rośnie i zbiega do nieskończoności, a nie do 0..
Wie ktoś jak temu zaradzić?

0

No nie wiem ale mogli byście pomóc, i powiedzieć co robię źle? :)

1
  1. Da się to co napisałeś zapisać prościej:
#include <stdio.h>
#include <math.h>

#define err 0.00001
 
double funkcja(double x) { return x*x+3/x; }

int main()
  {
   double x,nx;
   for(nx=1,x=0;fabs(nx-x)>err;printf("x=%lf; nx=%lf;\n",x,nx)) nx=funkcja(x=nx);
   printf("Poszukiwany pierwiastek to x=%lf\n",x);
   return 0;
  }

przy czym od razu pokazuje czemu tak to działa.
2. Mam spore wątpliwości co do zbieżności tego algorytmu.

2

Metoda iteracji prostej wymaga by funkcja w równaniu (x^2+3/x) była zbliżająca. Będzie tak gdy moduł pochodnej tej funkcji jest < 1. Twoja funkcja nie spełnia tego założenia.

0

Wasza pomoc jest nieoceniona, już wiem gdzie tkwi problem, jednak przekształciłem to równanie początkowe na kilka sposobów (dołączając x, pierwiastkując) znacie może ten dobry sposób aby iteracja na mojej funkcji zaczęła działać?

lista nie działających przekształceń:
x2+3/x
sqrt(x3+3)
x3-x2+x+3

1

x = \frac{3}{x^2} + 1

0

Po wprowadzeniu innej funkcji, po włączeniu programu w konsoli nic sie nie wyświetla, co może być przyczyną?

1

Pewnie pętla się nie kończy.

1

Poprawna pętla - kończy się bez problemu: http://ideone.com/9zlIb0

0

Pomimo tego, że Twoja pętla się zakończyła to wynik 1,86 nie zgadza się z wykresem tej funkcji. Można coś z tym zrobić?

2

Funkcja, którą podał @some_ONE jest błędna. Rozwiązujecie teraz równanie x<sup>3-x</sup>2-3=0.

0

Jednak rozwiązując -3/x2 + 1 dalej mam pustą konsolę,,

1

Źle mnie zrozumiałeś, równania x<sup>3-x</sup>2+3=0 i x=1-\frac{3}{x<sup>2} są co prawda równoważne, ale funkcja 1-\frac{3}{x</sup>2} nie spełnia wymaganych założeń. Trzeba szukać innej funkcji.

0

Szczerze mówiąc nie mam pomysłu na lepsze rozwiązania, ostatnim jest x2-x+(3/x)+1 jednak wynik tego działania to -1.#IND00 ( Przy czym poszukiwany wynik to -1,17~)

1

Ja znalazłem rozwiązanie -1.1745384894723214 korzystając z funkcji (x2-3)(1/3)

0

Używałem Twojego wzoru wcześniej, ale w konsoli otrzymuję przy nim wynik

00081dbcdd.png

Jak mogę poinstruować program aby poprawnie wyświetlił prawidłowy wynik?

1

Problem jest zapewne z podnoszeniem liczby ujemnej do potęgi ułamkowej. W Javie rozwiązałem to tak:

double f(double x)
{
    double podstawa = x*x - 3;
    if(podstawa>0)
    {
        return Math.pow(x*x-3,1.0/3);
    }
    else
    {
        return -Math.pow(3-x*x,1.0/3);
    }
}
0

Wielkie dzięki Bogdans, zadanie wykonane, ale możliwe że jeszcze się odezwę :) przede mną metoda Steffensena :)

0

Powracam z nowym pasjonującym zadaniem, jeśli ktoś ma chęć pomóc to zapraszam, a więc zaczynajmy:

Dana jest funkcja
ln(x)+x
cd645a95af.png

Naszym zadaniem jest znalezienie pierwiastków tej funkcji za pomocą metody Steffensena,
5210ff87a7.png
wykonałem wszystkie potrzebne zabiegi, podstawiłem pod wzór naszą funkcję i problem pozostaje w obliczeniach,
możliwe jest że zachodzi dzielenie przez 0, bądź coś innego co daje rezultat wyniku #ind,

dae3ac3578.png

#include "stdafx.h"
#include "stdio.h"
#include "conio.h"
#include "math.h"
 
double x0;  // x0 - punkt startowy
double x1;  // x1 - poszukiwany pierwiastek funkcji
double y;  // y - wartosc funkcji w punkcie x0
double g;  // g - warotsc funkcji g w punkcie x0
double blad=0.000001;  // blad -dokladnosc wyznaczenia pierwiastka

double funkcjaf(double x)
{
	return log(x)+x;   // licznik
}
double funkcjag(double x)
{
	return (log(x+x+log(x))+(x+x+log(x))-(log(x)+x))/(log(x)+x);  // mianownik
}
int main()
{
	x0=1.0;
	do
	{
		y=funkcjaf(x0);
		g=funkcjag(x0);
		x1=x0-y/g;
		x0=x1;
	}
	while(fabs(y)>=blad);
	printf("Poszukiwany pierwiastek to: %lf", x1);
	getch();
	return 0;
}
 

Jeśli ktoś ma pomysł jak rozwiązać ten problem to bardzo proszę :)
Pozdrawiam!

1

Masz dziwny warunek wyjścia z pętli. Dlaczego nie wypisujesz wartości pośrednich?

        y=funkcjaf(x0);
        g=funkcjag(x0);
        printf("y = %lf\n",y);
        printf("g = %lf\n",g);
        x1=x0-y/g;
        printf("x1 = %lf\n",x1);
        x0=x1;
0

Dzięki za pomoc, <ort>na prawdę</ort> dużo mi pomogłeś,

Dla ludzi którzy odwiedzą ten temat i będą mieli podobne problemy powiem że kolega wyżej miał rację, problem leżał w wyjściu z pętli.

Poprawny kod który daje dobry wynik to:

 #include "stdafx.h"
#include "stdio.h"
#include "conio.h"
#include "math.h"
 
double x0;  // x0 - punkt startowy
double x1;  // x1 - poszukiwany pierwiastek funkcji
double y;  // y - wartosc funkcji w punkcie x0
double g;  // g - warotsc funkcji g w punkcie x0
double blad=0.000001;  // blad -dokladnosc wyznaczenia pierwiastka
double wynik; // wynik pomocniczy

double funkcjaf(double x)
{
	return log(x)+x;   // licznik
}
double funkcjag(double x)
{
	return (log(x+x+log(x))+(x+x+log(x))-(log(x)+x))/(log(x)+x);  // mianownik
}
int main()
{
	x0=0.5;
	do
	{
		y=funkcjaf(x0);
        g=funkcjag(x0);
        printf("y = %lf\n",y);
        printf("g = %lf\n",g);
        x1=x0-y/g;
        printf("x1 = %lf\n",x1);
        x0=x1;
		wynik=fabs(x1-x0);
	}
	while(wynik>=blad);
	printf("Poszukiwany pierwiastek to: %lf", x1);
	getch();
	return 0;
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1