升压::数学算法:: ERF(Algorithm of boost::math::erf)

2019-09-17 07:36发布

是否有任何信息可供提升的ERF功能背后的算法? 该模块的文件是不是很精确。 所有我发现的是,几种方法进行混合。 对我来说,它看起来像阿布拉莫维茨和Stegun的变化。

  • 哪些方法混合使用吗?
  • 该方法是怎么混?
  • 什么是对ERF功能(恒定时间)的复杂性?

塞巴斯蒂安

Answer 1:

对于文档升压数学工具包有一长串的引用 ,其中阿布拉莫维茨和Stegun。 的叔-功能接口包含一个策略可用于控制数值精度(以及因此它的运行时间复杂度)的模板的参数。

#include <boost/math/special_functions/erf.hpp>
namespace boost{ namespace math{

template <class T>
calculated-result-type erf(T z);

template <class T, class Policy>
calculated-result-type erf(T z, const Policy&);

template <class T>
calculated-result-type erfc(T z);

template <class T, class Policy>
calculated-result-type erfc(T z, const Policy&);

}} // namespaces

更新

下面较早提供参考ERF功能的部分“执行”的完整副本:

履行

这些功能的所有版本首先使用通常的反射方程,使他们的论点正:

erf(-z) = 1 - erf(z);

erfc(-z) = 2 - erfc(z);  // preferred when -z < -0.5

erfc(-z) = 1 + erf(z);   // preferred when -0.5 <= -z < 0

这些函数的一般版本使用不完全伽玛功能方面实现。

当有效数(尾数)大小被识别(目前为53,64和113位的实数,加上通过促进加倍单精度的24位处理),则使用一系列由JM发明有理近似的。

对于z <= 0.5,则一个有理近似ERF被使用,基于这样的观察ERF为奇函数,因此ERF使用计算:

erf(z) = z * (C + R(z*z));

有效地,只要相对于常数C的绝对误差足够小,则R(Z * z)的计算期间所发生的任何舍入误差会:其中有理近似R(Z * Z)600是绝对误差优化从结果中消失。 因此在这个区域ERF ERFC和误差是非常低:最后一位是只有极少数病例不正确。

对于z> 0.5,我们观察到在一个小的区间[a,b)中,则:

erfc(z) * exp(z*z) * z ~ c

对于一些常数c。

因此对于z> 0.5,我们计算使用ERFC:

erfc(z) = exp(-z*z) * (C + R(z - B)) / z;

再次R(ž - B)为绝对误差的优化,和常数C是ERFC(Z)* EXP(Z * Z)*在该范围的端点所采取z的平均值。 再一次,只要R中的绝对误差 - 和C相比则c + R(Z - B)(Z B)是小将被正确地舍入,并且结果中的误差将在exp的精度仅取决于功能。 在实践中,但在所有极少数的情况下,错误被限制到结果的最后一位。 选择常数B,使得有理近似的范围的左手端是0。

对于大Z在一定范围内并[a,+∞]的上述近似被修改为:

erfc(z) = exp(-z*z) * (C + R(1 / z)) / z;

合理近似值中解释痛苦的细节 。 TF,你需要更多的细节,你可以随时看看源代码 。



文章来源: Algorithm of boost::math::erf