![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
Root-finding using Boost.MultiprecisionBoost , Math Toolkit 2.5.0 , Examples of Root-Finding (with and without derivatives)
|
![]() |
Tip |
---|---|
Чтобы гарантировать, что все потенциально значимые десятичные цифры отображаются, используйте< В идеале значения должны соответствовать< Это также означает, что «справочное» значение, которое должно бытьвходнымили< |
Если мы хотим вычислитьзначения более высокой точности, то на некоторых платформах мы можем использовать<long
double
>с более высокой точностью, чем<double
>, для сравнения с очень распространенным<double
>и/или более эффективным встроенным типом квадратной плавающей точки, таким как<__float128
>.
Почти все платформы могут легко использоватьBoost.Multiprecision, например,cpp_dec_floatили бинарный типcpp_bin_floatдля вычисления значений с гораздо большей точностью.
![]() |
Note |
---|---|
С многоточными типами спорно, использовать ли тип< |
Поскольку функторы и функции, используемые выше, шаблонизированы по типу значения, мы можем очень просто использовать их с любым из типовBoost.Multiprecision. В качестве напоминания, вот наша корневая функция игрушечного куба, использующая 2 производных и функции лямбды C++11, чтобы найти корень:
template <class T> T cbrt_2deriv_lambda(T x) { // return cube root of x using 1st and 2nd derivatives and Halley. //using namespace std; // Help ADL of std functions. using namespace boost::math::tools; int exponent; frexp(x, &exponent); // Get exponent of z (ignore mantissa). T guess = ldexp(1., exponent / 3); // Rough guess is to divide the exponent by three. T min = ldexp(0.5, exponent / 3); // Minimum possible value is half our guess. T max = ldexp(2., exponent / 3); // Maximum possible value is twice our guess. const int digits = std::numeric_limits<T>::digits; // Maximum possible binary digits accuracy for type T. // digits used to control how accurate to try to make the result. int get_digits = static_cast<int>(digits * 0.4); // Accuracy triples with each step, so stop when just // over one third of the digits are correct. boost::uintmax_t maxit = 20; T result = halley_iterate( // lambda function: [x](const T& g){ return std::make_tuple(g * g * g - x, 3 * g * g, 6 * g); }, guess, min, max, get_digits, maxit); return result; }
Ниже приведены примеры 50 десятичных знаков и двоичных типов (а на некоторых платформах гораздо более быстрый<float128
>или<quad_float
>тип), которые мы можем использовать с ними:
#include <boost/multiprecision/cpp_bin_float.hpp> // For cpp_bin_float_50. #include <boost/multiprecision/cpp_dec_float.hpp> // For cpp_dec_float_50. #ifndef _MSC_VER // float128 is not yet supported by Microsoft compiler at 2013. # include <boost/multiprecision/float128.hpp> // Requires libquadmath. #endif
Некоторые заявления упрощают их использование:
using boost::multiprecision::cpp_dec_float_50; // decimal. using boost::multiprecision::cpp_bin_float_50; // binary. #ifndef _MSC_VER // Not supported by Microsoft compiler. using boost::multiprecision::float128; #endif
Их можно использовать таким образом:
std::cout.precision(std::numeric_limits<cpp_dec_float_50>::digits10); cpp_dec_float_50 two = 2; // cpp_dec_float_50 r = cbrt_2deriv(two); std::cout << "cbrt(" << two << ") = " << r << std::endl; r = cbrt_2deriv(2.); // Passing a double, so ADL will compute a double precision result. std::cout << "cbrt(" << two << ") = " << r << std::endl; // cbrt(2) = 1.2599210498948731906665443602832965552806854248047 'wrong' from digits 17 onwards! r = cbrt_2deriv(static_cast<cpp_dec_float_50>(2.)); // Passing a cpp_dec_float_50, // so will compute a cpp_dec_float_50 precision result. std::cout << "cbrt(" << two << ") = " << r << std::endl; r = cbrt_2deriv<cpp_dec_float_50>(2.); // Explictly a cpp_dec_float_50, so will compute a cpp_dec_float_50 precision result. std::cout << "cbrt(" << two << ") = " << r << std::endl; // cpp_dec_float_50 1.2599210498948731647672106072782283505702514647015
Исходное значение, вычисляемоеWolfram Alpha
N[2^(1/3), 50] 1.2599210498948731647672106072782283505702514647015
Что точно согласуется.
Чтобыпоказатьзначения с их полной точностью, необходимо отрегулировать<std::ostream
><precision
>в соответствии с типом, например:
template <typename T> T show_cube_root(T value) { // Demonstrate by printing the root using all definitely significant digits. std::cout.precision(std::numeric_limits<T>::digits10); T r = cbrt_2deriv(value); std::cout << "value = " << value << ", cube root =" << r << std::endl; return r; }
show_cube_root(2.); show_cube_root(2.L); show_cube_root(two);
который выдает:
cbrt(2) = 1.2599210498948731647672106072782283505702514647015 value = 2, cube root =1.25992104989487 value = 2, cube root =1.25992104989487 value = 2, cube root =1.2599210498948731647672106072782283505702514647015
![]() |
Tip |
---|---|
Будьте очень осторожныв отношении типа плавающей точки< Даже< Еще более коварным является прохождение< |
Полный код этого примера находится по адресуroot_finding_multiprecision_example.cpp.
Статья Root-finding using Boost.Multiprecision раздела Math Toolkit 2.5.0 Examples of Root-Finding (with and without derivatives) может быть полезна для разработчиков на c++ и boost.
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.
:: Главная :: Examples of Root-Finding (with and without derivatives) ::
реклама |