⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 test_round.cpp

📁 Boost provides free peer-reviewed portable C++ source libraries. We emphasize libraries that work
💻 CPP
字号:
//  (C) Copyright John Maddock 2007.//  Use, modification and distribution are subject to the//  Boost Software License, Version 1.0. (See accompanying file//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)#include <boost/math/concepts/real_concept.hpp>#include <boost/test/included/test_exec_monitor.hpp>#include <boost/test/floating_point_comparison.hpp>#include <boost/math/special_functions/round.hpp>#include <boost/math/special_functions/trunc.hpp>#include <boost/math/special_functions/modf.hpp>#include <boost/math/special_functions/sign.hpp>#include <boost/random/mersenne_twister.hpp>boost::mt19937 rng;template <class T>T get_random(){   //   // Fill all the bits in T with random values,    // likewise set the exponent to a random value   // that will still fit inside a T, and always   // have a remainder as well as an integer part.   //   int bits = boost::math::tools::digits<T>();   int shift = 0;   int exponent = rng() % (bits - 4);   T result = 0;   while(bits > 0)   {      result += ldexp(static_cast<T>(rng()), shift);      shift += std::numeric_limits<int>::digits;      bits -= std::numeric_limits<int>::digits;   }   return rng() & 1u ? -ldexp(frexp(result, &bits), exponent) : ldexp(frexp(result, &bits), exponent);}template <class T, class U>void check_within_half(T a, U u){   BOOST_MATH_STD_USING   if(fabs(a-u) > 0.5f)   {      BOOST_ERROR("Rounded result differed by more than 0.5 from the original");      std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)         << std::left << a << u << std::endl;   }}//// We may not have an abs overload for long long so provide a fall back://template <class T>inline T safe_abs(T const& v ...){   return v < 0 ? -v : v;}template <class T, class U>void check_trunc_result(T a, U u){   BOOST_MATH_STD_USING   if(fabs(a-u) >= 1)   {      BOOST_ERROR("Rounded result differed by more than 1 from the original");      std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)         << std::left << a << u << std::endl;   }   if(abs(a) < safe_abs(u))   {      BOOST_ERROR("Truncated result had larger absolute value than the original");      std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)         << std::left << a << u << std::endl;   }}template <class T, class U>void check_modf_result(T a, T fract, U ipart){   BOOST_MATH_STD_USING   if(fract + ipart != a)   {      BOOST_ERROR("Fractional and integer results do not add up to the original value");      std::cerr << "Values were: " << std::setprecision(35) << " "         << std::left << a << ipart << " " << fract << std::endl;   }   if((boost::math::sign(a) != boost::math::sign(fract)) && boost::math::sign(fract))   {      BOOST_ERROR("Original and fractional parts have differing signs");      std::cerr << "Values were: " << std::setprecision(35) << " "         << std::left << a << ipart << " " << fract << std::endl;   }   if((boost::math::sign(a) != boost::math::sign(ipart)) && boost::math::sign(ipart))   {      BOOST_ERROR("Original and integer parts have differing signs");      std::cerr << "Values were: " << std::setprecision(35) << " "         << std::left << a << ipart << " " << ipart << std::endl;   }   if(fabs(a-ipart) >= 1)   {      BOOST_ERROR("Rounded result differed by more than 1 from the original");      std::cerr << "Values were: " << std::setprecision(35) << std::setw(40)         << std::left << a << ipart << std::endl;   }}template <class T>void test_round(T, const char* name){   BOOST_MATH_STD_USING   for(int i = 0; i < 1000; ++i)   {      T arg = get_random<T>();      T r = boost::math::round(arg);      check_within_half(arg, r);      r = boost::math::trunc(arg);      check_trunc_result(arg, r);      T frac = boost::math::modf(arg, &r);      check_modf_result(arg, frac, r);      if(abs(r) < (std::numeric_limits<int>::max)())      {         int i = boost::math::iround(arg);         check_within_half(arg, i);         i = boost::math::itrunc(arg);         check_trunc_result(arg, i);         r = boost::math::modf(arg, &i);         check_modf_result(arg, r, i);      }            if(abs(r) < (std::numeric_limits<long>::max)())      {         long l = boost::math::lround(arg);         check_within_half(arg, l);         l = boost::math::ltrunc(arg);         check_trunc_result(arg, l);         r = boost::math::modf(arg, &l);         check_modf_result(arg, r, l);      }#ifdef BOOST_HAS_LONG_LONG      if(abs(r) < (std::numeric_limits<boost::long_long_type>::max)())      {         boost::long_long_type ll = boost::math::llround(arg);         check_within_half(arg, ll);         ll = boost::math::lltrunc(arg);         check_trunc_result(arg, ll);         r = boost::math::modf(arg, &ll);         check_modf_result(arg, r, ll);      }#endif   }   //   // Finish off by testing the error handlers:   //   BOOST_CHECK_THROW(boost::math::iround(static_cast<T>(1e20)), boost::math::rounding_error);   BOOST_CHECK_THROW(boost::math::iround(static_cast<T>(-1e20)), boost::math::rounding_error);   BOOST_CHECK_THROW(boost::math::lround(static_cast<T>(1e20)), boost::math::rounding_error);   BOOST_CHECK_THROW(boost::math::lround(static_cast<T>(-1e20)), boost::math::rounding_error);#ifdef BOOST_HAS_LONG_LONG   BOOST_CHECK_THROW(boost::math::llround(static_cast<T>(1e20)), boost::math::rounding_error);   BOOST_CHECK_THROW(boost::math::llround(static_cast<T>(-1e20)), boost::math::rounding_error);#endif   if(std::numeric_limits<T>::has_infinity)   {      BOOST_CHECK_THROW(boost::math::round(std::numeric_limits<T>::infinity()), boost::math::rounding_error);      BOOST_CHECK_THROW(boost::math::iround(std::numeric_limits<T>::infinity()), boost::math::rounding_error);      BOOST_CHECK_THROW(boost::math::iround(-std::numeric_limits<T>::infinity()), boost::math::rounding_error);      BOOST_CHECK_THROW(boost::math::lround(std::numeric_limits<T>::infinity()), boost::math::rounding_error);      BOOST_CHECK_THROW(boost::math::lround(-std::numeric_limits<T>::infinity()), boost::math::rounding_error);   #ifdef BOOST_HAS_LONG_LONG      BOOST_CHECK_THROW(boost::math::llround(std::numeric_limits<T>::infinity()), boost::math::rounding_error);      BOOST_CHECK_THROW(boost::math::llround(-std::numeric_limits<T>::infinity()), boost::math::rounding_error);   #endif   }   if(std::numeric_limits<T>::has_quiet_NaN)   {      BOOST_CHECK_THROW(boost::math::round(std::numeric_limits<T>::quiet_NaN()), boost::math::rounding_error);      BOOST_CHECK_THROW(boost::math::iround(std::numeric_limits<T>::quiet_NaN()), boost::math::rounding_error);      BOOST_CHECK_THROW(boost::math::lround(std::numeric_limits<T>::quiet_NaN()), boost::math::rounding_error);   #ifdef BOOST_HAS_LONG_LONG      BOOST_CHECK_THROW(boost::math::llround(std::numeric_limits<T>::quiet_NaN()), boost::math::rounding_error);   #endif   }   BOOST_CHECK_THROW(boost::math::itrunc(static_cast<T>(1e20)), boost::math::rounding_error);   BOOST_CHECK_THROW(boost::math::itrunc(static_cast<T>(-1e20)), boost::math::rounding_error);   BOOST_CHECK_THROW(boost::math::ltrunc(static_cast<T>(1e20)), boost::math::rounding_error);   BOOST_CHECK_THROW(boost::math::ltrunc(static_cast<T>(-1e20)), boost::math::rounding_error);#ifdef BOOST_HAS_LONG_LONG   BOOST_CHECK_THROW(boost::math::lltrunc(static_cast<T>(1e20)), boost::math::rounding_error);   BOOST_CHECK_THROW(boost::math::lltrunc(static_cast<T>(-1e20)), boost::math::rounding_error);#endif   if(std::numeric_limits<T>::has_infinity)   {      BOOST_CHECK_THROW(boost::math::trunc(std::numeric_limits<T>::infinity()), boost::math::rounding_error);      BOOST_CHECK_THROW(boost::math::itrunc(std::numeric_limits<T>::infinity()), boost::math::rounding_error);      BOOST_CHECK_THROW(boost::math::itrunc(-std::numeric_limits<T>::infinity()), boost::math::rounding_error);      BOOST_CHECK_THROW(boost::math::ltrunc(std::numeric_limits<T>::infinity()), boost::math::rounding_error);      BOOST_CHECK_THROW(boost::math::ltrunc(-std::numeric_limits<T>::infinity()), boost::math::rounding_error);   #ifdef BOOST_HAS_LONG_LONG      BOOST_CHECK_THROW(boost::math::lltrunc(std::numeric_limits<T>::infinity()), boost::math::rounding_error);      BOOST_CHECK_THROW(boost::math::lltrunc(-std::numeric_limits<T>::infinity()), boost::math::rounding_error);   #endif   }   if(std::numeric_limits<T>::has_quiet_NaN)   {      BOOST_CHECK_THROW(boost::math::trunc(std::numeric_limits<T>::quiet_NaN()), boost::math::rounding_error);      BOOST_CHECK_THROW(boost::math::itrunc(std::numeric_limits<T>::quiet_NaN()), boost::math::rounding_error);      BOOST_CHECK_THROW(boost::math::ltrunc(std::numeric_limits<T>::quiet_NaN()), boost::math::rounding_error);   #ifdef BOOST_HAS_LONG_LONG      BOOST_CHECK_THROW(boost::math::lltrunc(std::numeric_limits<T>::quiet_NaN()), boost::math::rounding_error);   #endif   }}int test_main(int, char* []){   test_round(0.1F, "float");   test_round(0.1, "double");#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS   test_round(0.1L, "long double");   //test_round(boost::math::concepts::real_concept(0.1), "real_concept");#else   std::cout << "<note>The long double tests have been disabled on this platform "      "either because the long double overloads of the usual math functions are "      "not available at all, or because they are too inaccurate for these tests "      "to pass.</note>" << std::cout;#endif   return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -