稳健而准确地计算两个浮点数的商的自然对数

时间:2018-08-06 22:00:26

标签: c algorithm floating-point logarithm

在计算log (a/b)时一个明显的问题是,ab是给定精度(此处称为本机精度)的两个非零正有限浮点操作数。 a/b商不能以这种精度表示为浮点数。此外,当源操作数的比率接近于1时,精度将丢失。

可以通过暂时切换到更高精度的计算来解决此问题。但是,例如在本机精度为double并且long double仅映射到double时,可能无法轻易获得这种更高的精度。使用高精度计算还可能对性能产生非常显着的负面影响,例如,在GPU上,float计算的吞吐量可能是double计算吞吐量的32倍。 / p>

一个人可能决定使用对数的quotient rule来计算log (a/b)log(a) - log(b),但是当a时,这会使计算面临subtractive cancellation的风险。和b彼此靠近,导致非常大的错误。

如何精确计算给定精度的两个浮点数的商的对数,例如是否具有小于2 ulps的误差且鲁棒性强,即在不求助于高于本机精度计算的情况下,中间计算中没有下溢和溢出?

1 个答案:

答案 0 :(得分:5)

到目前为止,我确定的最佳方法将三种情况区分开来,这三种情况是基于较大源操作数除以较小源操作数的商。该比率告诉我们操作数相距多远。如果它太大而超过了本机精度的最大可表示数字,则必须使用商规则,并且结果将计算为log(a) - log(b)。如果比率接近于1,则计算应利用函数log1p()来提高准确性,并将结果计算为log1p ((a - b) / b)Sterbenz Lemma表示2.0是一个很好的切换点,因为如果{≤{1}}的比率等于或小于2,则将精确计算{{1}。 }}。

下面,我将演示此设计的实现方法,该函数接受a-b个参数。使用log (a/b)可以更轻松地评估准确性,因为这样可以对可能的测试用例进行更密集的采样。显然,整体准确性将取决于数学库中floatfloat的实现质量。使用具有几乎正确舍入的函数的数学库(logf()中的最大误差<0.524 ulp,logpf()中的最大误差<0.506 ulp),在logf()中观察到的最大误差为<1.5 ulps。使用不同的库,对函数进行如实的全面实现(log1pf()中的最大错误<0.851 ulp,log_quotient()中的最大错误<0.874 ulp),logf()中观察到的最大错误是<1.7 ulps。

log1pf()