Sprawdzenie poprawności metody całkowania

0

Witam, mam wielki problem.. otóż nie wiem czy podany poniżej program działać bedzie poprawnie.. A dokładnie czy nie ma w nim błędów z dziedziny metod numerycznych. Mam do scałkowania dość skomplikowaną funkcję i nie wiem czy ten program poda mi prawidłowe rozwiązania.
Dziękuje ze pomoc i ewentualne sugestie!

#include <iomanip>
#include <iostream>
#include <math.h>

using namespace std;

double f(double x)
{
  return(sqrt(x) * 2 * pow((0,0002) - (0,342 - x)*(0,342 - x), 1/2));
}



int main()
{
  const int N = 100000; //liczba punktów/trapezów podziałowych
  double xp,xk,s,dx;
  int i;

  cout.precision(5);      // 5 cyfry po przecinku
  cout.setf(ios::fixed);  // format stałoprzecinkowy

  cout << "Obliczanie  calki oznaczonej\n"
          " za pomoca  metody trapezow\n"
          "----------------------------\n"
          
          "Podaj poczatek przedzialu calkowania\n\n"
          "xp = ";
  cin >> xp;
  cout << "\nPodaj koniec przedzialu calkowania\n\n"
          "xk = ";
  cin >> xk;
  cout << endl;

  s  = 0;
  dx = (xk - xp) / N;
  for(i = 1; i < N; i++) s += f(xp + i * dx);
  s = (s + (f(xp) + f(xk)) / 2) * dx;
  cout << "Wartosc calki wynosi : " << setw(8) << s
       << "\n\n";
  system("PAUSE"); return 0;
}

</i>
0

sqrt(x) * 2 * pow((0.0002) - (0.342 - x)*(0.342 - x), 1/2);
ale:
pow(y, 1/2) = sqrt(y)

wyrażenie pierwiastkowane nie może być tu ujemne:
0.0002 - (0.342 - x)*(0.342 - x) >= 0
(0.342 - x)^2 <= 0.0002
czyli x musi leżeć w takim wąskim przedziale:
0.342 - sqrt(0.0002), 0.342 + sqrt(0.0002);
jest to w przbliżeniu <0.328, 0.356>

Błąd zależy od pochodnej, więc dobrze aby była ograniczona:
sqrt(c - (a - x)2)' = (a-x)/sqrt(c - (a - x)2)
widać, że w punktach gdzie: c - (a - x)^2 = 0 pochodna będzie nieskończona,
są to końce wcześniej obliczonego przedziału.

0
wil napisał(a)

sqrt(x) * 2 * pow((0.0002) - (0.342 - x)*(0.342 - x), 1/2);
ale:
pow(y, 1/2) = sqrt(y)

Tak, ale z jakiegoś powodu nie chciał mi tego kompilator przełknąć ;)

wil napisał(a)

wyrażenie pierwiastkowane nie może być tu ujemne:
0.0002 - (0.342 - x)*(0.342 - x) >= 0
(0.342 - x)^2 <= 0.0002
czyli x musi leżeć w takim wąskim przedziale:
0.342 - sqrt(0.0002), 0.342 + sqrt(0.0002);
jest to w przbliżeniu <0.328, 0.356>

Zgadza się, są to dokładnie wartości z przedziału <0,327 ; 0,357>

wil napisał(a)

Błąd zależy od pochodnej, więc dobrze aby była ograniczona:
sqrt(c - (a - x)2)' = (a-x)/sqrt(c - (a - x)2)
widać, że w punktach gdzie: c - (a - x)^2 = 0 pochodna będzie nieskończona,
są to końce wcześniej obliczonego przedziału.

A tego to nie rozumiem... Jak się to ma do poprawności procedury?
Ja po prosru chciałbym wiedzieć czy tak napisany program jest merytorycznie poprawny, czy wszystko jest na swoim miejscu... czy będzie działał tak jak powinien :)

POzdrawiam!!

0

Metoda trapezów jest dobra, ale nie dla tej funkcji w tym przedziale.

Stałe liczby rzeczywste w c wyglądają tak: 0.887,
a takie coś: 0,887 jest wyrażeniem o wartości 887.

0

pow(y,1/2) == pow(y, 0) == 1, ponieważ 1/2 == 0. Czyż nie?

Myślałem, że znam jeszcze ciekawszą historię o przecinku, okazała się nieprawdziwa ale i tak jest ciekawa.
Zobaczcie też to: Famous computer bugs.

0

Więc jaka metoda jest dorba dla tej funkcji.. w tym przedziale???

Akurat w samym kodzie programu nie ma chyba znaczenia czy jest ","
czy "." - wynik pozostaje taki sam :)

A o co chodzi z tym pierwiastkiem? Jak zmianiam z pow() na sqrt(), to jako wynik całki pojawia mi się: -1.#INDO

0
BarTh napisał(a)

Akurat w samym kodzie programu nie ma chyba znaczenia czy jest ","
czy "." - wynik pozostaje taki sam :)

:| tak sie sklada, ze w c, na oznaczanie liczby ulamkowej z przecinkiem uzywa sie '.' (kropki).

0

Zmieniałem na kropki... działa tak samo... Pytanie tylko czy dobrze? I raz jeszcze spytam: o co chodzi z tymi pierwiastkami? Jak zmieniam z 1/2 na 0.5 to się pojawia błąd taki napisalem w poście wyrzej... :-/

POzdrawiam!!

0
BarTh napisał(a)

Więc jaka metoda jest dorba dla tej funkcji.. w tym przedziale???

Metoda trapezów też to obliczy, ale liczba przedziałów musi być kosmicznie duża -
zazwyczaj tysiąc przedziałów wystarcza dla obliczenia z dokładnością do kilkunastu cyfr,
a tu trzeba miliardy - zbieżność jest tylko liniowa, a powinna być kwadratowa.

Są też tzw. kwadratury otwarte... i chyba tu się lepiej sprawdzą od zamkniętych (trapezy, simpson, ...)

  • najprostszy jest wzór prostokątów.

Najlepiej pasuje (do tego pierwiastka):
kwadratura Gaussa z funkcją wagową sqrt(1 - x^2) -> wielomiany Czybyszewa II rodzaju.

BarTh napisał(a)

Akurat w samym kodzie programu nie ma chyba znaczenia czy jest ","
czy "." - wynik pozostaje taki sam

Jeśli 0.5 = 5 to tak będzie jak mówisz. :-)

0

Raz jeszcze spytam: o co chodzi z tymi pierwiastkami? Jak zmieniam z 1/2 na 0.5 to się pojawia błąd - a dokładniej jako wnik otrzymuję: -1.#INDO

A co do tych przecinków i kropek... ja tylko pisze jak to wygląda po uruchomieniu programu... i wyniki są w obu przypadkach takie same... Może błąd jest gdzieś indziej i <I>ON</I> liczy zupłnie co innego?

POzdrawiam!!

0

Ten błąd to pierwiastek z liczby ujemnej - zły przedział całkowania,
czyli poza tym wąskim przedziałem w otoczeniu 0.3xx.
Musisz sprawdzać czy obie granice wchodzą do tego przedziału, jeśli nie to korygować -
jest ten dozwolony przedział: <minx, maxx>:

if( a < minx ) a = mina;
if( b > maxx ) b = maxx;

Wynik dla tego dopuszczalnego przedziału, czyli w granicach:
a = 0.32785786437627, b = 0.35614213562373
( 'a' zaokrąglamy w górę, a 'b' w dół, aby uniknąć pierwiastka z ujemnej)

I<a, b>[2*sqrt(x)*sqrt(0.0002 - (0.342 - x)^2] = 0.000367

0

Wielkie dzięki!! Oto mi własnie chodziło.
Zaraz to wszystko u siebie sprawdzę.

POzdrawiam!!

0

Chcialem zauwazyc, ze w C 1/2 nie jest rowna 0.5, bo 1/2 == 0 !!!

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