用多重新计算提高间隔
Boost Interval with Multiprecision
我尝试将boost Interval算术库与Boost MultipRecision库一起使用。如果我使用本机双重数据类型使用标准的双重精度,则一切正常。
使用多重新计算库,它产生的结果实际上更不准确。这里有一些代码:
#include <boostnumericinterval.hpp>
#include <boostmultiprecisioncpp_dec_float.hpp>
#include <iostream>
using namespace boost::numeric;
using namespace boost::numeric::interval_lib;
using namespace boost::multiprecision;
template <typename T>
using Interval = interval<T, policies<save_state<rounded_transc_exact<T>>, checking_base<T>>>;
using BigFloat = cpp_dec_float_100;
int main()
{
std::cout << sin(Interval<double>(0.0, 0.1)).upper() << "n"; // 0.0998334
std::cout << sin(Interval<BigFloat>(0.0, 0.1)).upper() << "n"; // 1
}
可以看出,double
版本产生非常准确的结果。BigFloat
版本应该更准确,但是它会产生非常大的界限 - 实际上是sin
函数的最大值,因此该界限完全没有用。
如何解决此问题,以使间隔库实际上利用更高的精度并产生更尖锐的界限?
要开始,我用 cos
而不是 sin
进行了测试。
与cos(x-½π)
一样,间隔库实现sin(x)
。这意味着sin([0, 0.1])
转换为cos([-½π,-½π+0.1])
(递归到cos([½π,½π+0.1])
)。
在BigFloat的情况下,由于库不知道PI常数(pi<BigFloat>()
,pi_half<BigFloat>()
或pi_twice<BigFloat>()
),它代表它们为整数间隔,例如:pi_half<BigFloat>
表示为[1,2]。糟糕。cos间隔已成为[-2,-0.9]
(递归到[0,3.1]
面中)。
添加一些跟踪:
DOUBLE--------------------
pi/2: [1.570796326794896558,1.57079632679489678]
sin: [0,0.10000000000000000555]
cos: [-1.57079632679489678,-1.4707963267948964692]
cos: [1.5707963267948961139,1.6707963267948979791]
[-5.0532154980743028885e-16,0.099833416646829500896]
BigFloat--------------------
pi/2: [1,2]
sin: [0,0.10000000000000000555]
cos: [-2,-0.89999999999999999445]
cos: [0,3.1000000000000000056]
[-1,1]
解决方案?
我可以想到的最好的解决方案涉及直接使用cos
或专门使用pi_half
:
直接使用cos
这不是解决方案,因为它仍然会在内部使用某些损坏的pi_*<BigFloat>()
常数:
static BigFloat bf_pi_half() { return bmp::default_ops::get_constant_pi<BigFloat::backend_type>() / BigFloat(2); }
现在您可以写
活在coliru
std::cout << "BigFloat--------------------n";
std::cout << cos(ival - bf_pi_half()) << "n";
打印
BigFloat--------------------
[-0.909297,0.818277]
您可以看到,这不是所需的输出。
专业常数
实际上,您应该专门研究基础常数:
活在coliru
#include <iostream>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <boost/multiprecision/detail/default_ops.hpp>
#include <boost/numeric/interval.hpp>
#include <boost/numeric/interval/io.hpp>
namespace bn = boost::numeric;
namespace bni = bn::interval_lib;
namespace bmp = boost::multiprecision;
template <typename T>
using Interval = bn::interval<T, bni::policies<bni::save_state<bni::rounded_transc_exact<T>>, bni::checking_base<T>>>;
using BigFloat = bmp::cpp_dec_float_100; // bmp::number<bmp::backends::cpp_dec_float<100>, bmp::et_off>;
static BigFloat bf_pi() { return bmp::default_ops::get_constant_pi<BigFloat::backend_type>(); }
namespace boost { namespace numeric { namespace interval_lib { namespace constants {
template<> inline BigFloat pi_lower<BigFloat>() { return bf_pi(); }
template<> inline BigFloat pi_upper<BigFloat>() { return bf_pi(); }
template<> inline BigFloat pi_twice_lower<BigFloat>() { return bf_pi() * 2; }
template<> inline BigFloat pi_twice_upper<BigFloat>() { return bf_pi() * 2; }
template<> inline BigFloat pi_half_lower<BigFloat>() { return bf_pi() / 2; }
template<> inline BigFloat pi_half_upper<BigFloat>() { return bf_pi() / 2; }
} } } }
int main() {
std::cout << sin(Interval<BigFloat>(0, 0.1)) << "n";
}
此打印:
[0,0.0998334]
¹实际上使用pi_twice<>
常量
相关文章:
- 计算每个节点的树高,帮助我解释这个代码解决方案
- 高CPU使用率,在API桌面复制中获取帧之间具有不同的超时间隔
- 计算速度与间隔反向比率
- MFC 用于计算控件的高光、阴影等的算法或函数是什么?
- 如何计算在重复数字之前 x 必须在 (x * y) % z 中有多高
- 有效的方法来计算浮子后下一个更高的整数
- 用多重新计算提高间隔
- 在一系列数字的间隔内计算数字
- 高精度计算平均值的最佳策略
- C 矢量阵列操作员高计算成本
- 如何实现计算的高斯核
- OpenCV C++使用高斯核函数计算晕影效应
- 计算线间隔中的点数
- 计算效率高的C++-一般阅读
- 大变量的高阶贝塞尔函数计算
- 定时间隔总是计算为零
- 高斯-塞德尔法计算3个系统的线性方程
- 实现高斯模糊-如何计算卷积矩阵(核)
- GPS跟踪,计算高差
- 我如何优化高斯pdf的计算