Skip to content

Instantly share code, notes, and snippets.

@typeofweb
Forked from anonymous/mn4.cpp
Last active December 17, 2015 00:29
Show Gist options
  • Save typeofweb/5521750 to your computer and use it in GitHub Desktop.
Save typeofweb/5521750 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <vector>
using std::cout;
using std::cin;
template <class T>
struct Fun {
const T operator()(T x) { // funkcja
//return -5*x*x*x+8*x*x+3*x-1;
//return x*x*x-2*x+2;
return std::log(x+2) - 2*x*x + 1;
}
const T d1(T x) { // jej pierwsza pochodna
//return -15*x*x+16*x+3;
//return 3*x*x-2;
return 1.0 / (x+2) - 4*x;
}
const T d2(T x) { // jej druga pochodna
//return -30*x+16;
//return 6*x;
return - 1.0 / ((x+2.0)*(x+2.0)) - 4.0;
}
};
template <class T>
std::pair<T, unsigned> bisection (T a, T b, T eps = 1e-6, unsigned it_bnd = 10000) {
if (a > b) {
std::swap(a, b); // a i b zawsze w odpowiedniej kolejności
}
Fun<T> f;
if (f(a) * f(b) > 0) { // warunek różnych znaków na krańcach przedziału
throw std::runtime_error("Brak rozwiazan w tym przedziale!");
}
unsigned it_cnt = 0;
for (; std::abs(b - a) >= eps && it_bnd > it_cnt; ++it_cnt) {
T c = (a + b) / 2.0; // kolejny krok iteracji
if (f(a) * f(c) <= 0.0) {
b = c;
} else {
a = c;
}
}
T fa = f(a), fx = f((a + b) / 2.0), fb = f(b); // sprawdzenie warunku na asymptotę
if ( (fa > fx && fx > fb) || (fa < fx && fx < fb) ) { // jeśli krańce oraz środek przedziału z ostatniej iteracji nie są monotoniczne to mamy asymptotę
return std::make_pair((a + b) / 2.0, it_cnt);
} else {
std::runtime_error("Znaleziono asymptote pionowa!");
}
}
template <class T>
std::pair<T, unsigned> tangents (T a, T b, T eps = 1e-6, unsigned it_bnd = 10000) {
if (a > b) {
std::swap(a, b); // a i b zawsze w odpowiedniej kolejności
}
Fun<T> f;
if (f(a) * f(b) > 0) { // warunek różnych znaków na krańcach przedziału
throw std::runtime_error("Brak rozwiazan w tym przedziale!");
}
T xk;
if (f(a) * f.d2(a) > 0) { // znalezienie wartości x0 zgodnie ze skryptem Ratajczaka
xk = a;
} else if (f(b) * f.d2(b) > 0) {
xk = b;
} else {
throw std::runtime_error("Przedzial nie spelnia zalozen!");
}
T m = std::min(std::abs(f.d1(a)), std::abs(f.d1(b)));
unsigned it_cnt = 1;
for (; std::abs(f(xk)) / m >= eps && it_bnd > it_cnt; ++it_cnt) {
xk = xk - (f(xk) / f.d1(xk)); // kolejny krok iteracji
}
if (xk >= a && xk <= b) {
return std::make_pair(xk, it_cnt);
} else {
std::runtime_error("Znaleziono asymptote pionowa!");
}
}
template<class T>
void start (T a, T b, T eps = 1e-11, T step = 0.1) {
if (a > b) {
std::swap(a, b);
}
std::vector<std::pair<T,T>> intervals;
Fun<T> f;
for (T ia = a, ib = (a + step); ib <= b; ib += step) {
if (f(ia) * f(ib) < 0.0) {
if (std::abs(ib) < eps) {
ib = step;
}
intervals.push_back(std::make_pair(ia, ib));
}
ia = ib;
}
for (auto it = intervals.begin(); it != intervals.end(); ++it) {
try {
std::pair<T, unsigned> sol = bisection<T>((*it).first, (*it).second, eps);
cout << "Bisekcje:\t" << ((std::abs(sol.first) < eps) ? 0.0 : sol.first) << "\n";
cout << "Ilosc iteracji:\t" << sol.second << "\n\n";
} catch (std::runtime_error e) {
cout << e.what() << "\n\n";
}
try {
std::pair<T, unsigned> sol = tangents<T>((*it).first, (*it).second, eps);
cout << "Styczne:\t" << ((std::abs(sol.first) < eps) ? 0.0 : sol.first) << "\n";
cout << "Ilosc iteracji:\t" << sol.second << "\n\n";
} catch (std::runtime_error e) {
cout << e.what() << "\n\n";
}
}
}
int main () {
cout.setf(std::ios::adjustfield);
//cout.setf(ios::fixed);
cout.precision(10);
start<double>(-3.0, 3.0, 1e-11, 0.1);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment