• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Jak znaleźć konkretne miejsca zerowe podanej funkcji? Co poprawić? Jakie błędy?

Object Storage Arubacloud
0 głosów
567 wizyt
pytanie zadane 27 marca 2018 w C i C++ przez Seyn Początkujący (300 p.)

Witam!

Próbuję rozwiązać zadanie 71.3, którego treść jest w podanym linku na stronie 133/134: LINK.

Mam znaleźć wszystkie miejsca zerowe z dokładnością do 5 miejsc po przecinku z tym, że nie bardzo wiem jaki warunek w ostatnim IFie zawrzeć aby w tablicy znalazły się wyłącznie poprawne według klucza (podane niżej) odpowiedzi. Dla kodu przedstawionego poniżej wypisanych jest 11 miejsc zerowych: 

( 0.53657; 0.53658; 0.53659; 0.5366; 2.52071; 2.52072; 2.52073; 3.3177; 3.31771; 4.8497; 4.84971;),

które jak widać są bardzo podobne. Gdy zmienie warunek na  "  if(pom>=0 &&pom<0.00004)  "  wypisane są ( 0.53657; 0.53658; 2.52073; 3.3177; 4.84971;)  natomiast dobrze wiem, że przecież nie będę tak sobie cudował o jedną dziesięciotysięczną aż osiągnę prawidłowy wynik tylko muszę to jakoś lepiej napisać.

Byłbym wdzięczny za podpowiedź jak i również sugestie jak mógłbym kod zmodyfikować  aby było czytelniej, krócej i bardziej profesjonalnie. Bo te IFy dla każdej funkcji też mnie gryzą w oczy ale to zadanie maturalne i starałem się napisać to jak najszybciej laugh
 

Prawidłowa odpowiedź to: 

  • Miejsce zerowe: 0.53656
  • Miejsce zerowe: 2.52073
  • Miejsce zerowe: 3.31769
  • Miejsce zerowe: 4.84971
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cmath>
using namespace std;
ofstream fout("wyniki.txt");

double f1(double x)
{
    return(-1.00000+1.80861*x+0.00000*x*x+0.19139*x*x*x);
}
double f2(double x)
{
    return(1.14833-4.63636*x+6.44498*x*x-1.95694*x*x*x);
}
double f3(double x)
{
    return(-51.59809+74.48325*x-33.11483*x*x+4.63636*x*x*x);
}
double f4(double x)
{
    return(224.47368-201.58852*x+58.90909*x*x-5.58852*x*x*x);
}
double f5(double x)
{
    return(-307.12440+197.11005*x-40.76555*x*x+2.71770*x*x*x);
}


void zad3()
{
    double x=0.00000, pom=0;
    double tab[20]={0}; int k=0;
    while(x<5)
    {
        if(x>=0 &&x<1)
            pom=f1(x);
        if(x>=1 &&x<2)
            pom=f2(x);
        if(x>=2 &&x<3)
            pom=f3(x);
        if(x>=3 &&x<4)
            pom=f4(x);
        if(x>=4 &&x<5)
            pom=f5(x);

        if(pom>=0 &&pom<0.00009)
        {
            tab[k]=x;
            cout<<setprecision(9)<<tab[k]<<endl;
            k++;

        }
        x=x+0.00001;
    }

}

int main()
{
    zad3();

    return 0;
}



 

Gdyby ktoś miał chęć, byłbym bardzo wdzięczny o ocenę rozwiazania CKE do tego zadania znajdującego się na stronie 312/313 podanego pliku, ponieważ za bardzo go nie rozumiem. Czas na maturze najcenniejszy a mam wrażenie, że oni przekombinowali. Aczkolwiek jestem jeszcze zielony także prosiłbym o opinię bardziej doświadczonych koderów :)

Pozdro :)

2 odpowiedzi

+1 głos
odpowiedź 27 marca 2018 przez softkdp Obywatel (1,060 p.)
Generalnie szukając miejsc zerowych funkcji na jakimś przedziale najczęściej sprawdza się czy funkcja zmienia znak (wtedy na pewno przechodzi przez zero). Można do tego wykorzystać warunek if (f(a)*f(b) < 0) dla a i b - krańców przedziału. Z tak małym krokiem jak 0.00001 powinieneś uniknąć kłopotliwej sytuacji gdy przedział jest zbyt duży i są na nim np. 2 miejsce zerowe i funkcja znowu wróci do wartości dodatniej.
+1 głos
odpowiedź 27 marca 2018 przez niezalogowany

Rozwiązanie od CKE to typowa implementacja bisekcji - tylko trzeba wiedzieć jak ona działa. Problem tworzenia 5 różnych funkcji rozwiązali przez globalne zmienne - jest jedna funkcja f dla której dostępne są parametry a0-a4 (A-D) wielomianu. Mógłbyś zrobić podsyłać wszystkie parametry i x, albo stworzyć strukturę wielomian z przeciążonym operatorem ().

#include <iostream>
#include <fstream>
#include <iomanip>

struct Polynomial4th {
	double a0, a1, a2, a3;

	double operator()(double x) {
		return a0 + a1*x + a2*x*x + a3*x*x*x;
	}
};

double bisection(Polynomial4th f, double a, double b);

int main()
{
	std::ifstream fin("funkcja.txt");
	std::ofstream fout("wyniki_funkcja.txt");
	double ranges[6] { 0, 1, 2, 3, 4, 5 };
	fout << std::fixed << std::setprecision(5);

	for (size_t i = 1; i < 6); ++i) {
		Polynomial4th f;
		fin >> f.a0 >> f.a1 >> f.a2 >> f.a3;
		double a = ranges[i - 1], b = ranges[i];
		if (f(a) * f(b) < 0) { // zalozenie bisekcji nie spelni sie dla przedzialu (1, 2)
			fout << bisection(f, a, b) << "\n";
		}
	}
}

double bisection(Polynomial4th f, double a, double b) { // implementacja z Wikipedii
	static const double epsilon = 1.e-6, residuum = 1.e-6;
	double x0, f0;
	while (b - a > epsilon) {
		x0 = (a + b) / 2;
		f0 = f(x0);
		if (std::abs(f0) <= residuum) {
			break;
		}
		else if (f0 * f(a) < 0) {
			b = x0;
		}
		else {
			a = x0;
		}
	}
	return x0;
}

Pamiętaj używać std::setprecision z std::fixed gdy chcesz osiągnąć jakąś dokładność po przecinku. Zawsze gdy dane są w jakimś osobnym pliku to należy je pobrać, a nie kopiować bezpośrednio do kodu.

Podobne pytania

0 głosów
1 odpowiedź 228 wizyt
pytanie zadane 14 grudnia 2016 w SQL, bazy danych przez niezalogowany
0 głosów
1 odpowiedź 824 wizyt
pytanie zadane 13 października 2018 w C# przez aXen Początkujący (390 p.)
+1 głos
0 odpowiedzi 95 wizyt
pytanie zadane 7 czerwca 2023 w Matematyka, fizyka, logika przez Konrad4142 Nowicjusz (130 p.)

92,565 zapytań

141,416 odpowiedzi

319,598 komentarzy

61,948 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...