Algorithm pow算法(浮点,浮点)

Algorithm pow算法(浮点,浮点),algorithm,math,floating-point,c,Algorithm,Math,Floating Point,C,我需要一个有效的算法来做数学::两个浮点数之间的幂函数, 你知道怎么做吗,(我需要算法不使用函数本身)一般算法倾向于将浮点幂计算为整数幂和剩余根的组合。整数幂相当简单,可以使用或计算根。IIRC对此有一些说明。还有其他(可能更好的)方法可以做到这一点,但这将为实现一个异常复杂的问题提供一个合理的起点。还请注意,一些实现使用查找表和一些技巧来减少所需的计算。由于IEEE-754二进制浮点数是分数,计算ab在技术上是一种代数运算。然而,实现powf(浮点a,浮点b)的常用方法是eb*log a,即使

我需要一个有效的算法来做数学::两个浮点数之间的幂函数,
你知道怎么做吗,(我需要算法不使用函数本身)

一般算法倾向于将浮点幂计算为整数幂和剩余根的组合。整数幂相当简单,可以使用或计算根。IIRC对此有一些说明。还有其他(可能更好的)方法可以做到这一点,但这将为实现一个异常复杂的问题提供一个合理的起点。还请注意,一些实现使用查找表和一些技巧来减少所需的计算。

由于IEEE-754二进制浮点数是分数,计算ab在技术上是一种代数运算。然而,实现powf(浮点a,浮点b)的常用方法是eb*log a,即使用超越函数

然而,有一些警告<对于
a<0
,code>log a是未定义的,而
powf()
允许使用一些负数
a
进行计算。正如我在对的回答中所解释的那样,以
expf()。这要求我们以高于单个精度的
log a
计算准确的
powf()
结果。有多种技术可以实现这一点,一种简单的方法是使用有限数量的double-
float
计算,我在对的回答中提供了相关参考。double-
float
的本质是,每个浮点操作数都表示为一对称为“head”和“tail”的
float
值,它们满足| tail |≤ ½*(|头|)正常化时

下面的代码显示了该方法的示例性实现。它假设IEEE 754-2008操作FMA(融合乘法加法)可用,它在C中作为标准数学函数
FMA()
fmaf()
公开。它没有规定如何处理
errno
或浮点异常,但它确实规定如何正确处理ISO C标准列举的所有18种特殊情况。已在启用非规范化支持的情况下执行测试;该代码可能在非IEEE-754零位齐平(FTZ)环境中正常工作,也可能无法正常工作

求幂部分采用直接基于浮点数的半对数编码的简单参数缩减,然后在主近似区间上应用多项式。对数计算基于
log(x)=2 atanh((x-1)/(x+1))
,结合选择性地使用双浮点数计算,以达到8.3e-10的相对精度。
b*log a
的计算作为双-
float
运算执行,通过观察ex是其自身的导数,因此ex+y,通过线性插值提高最终幂运算的精度≅ ex+y⋅ 例如,当| y |≪ |x |

Double-
float
在溢出边界附近的计算变得有点不确定,代码中有两个实例。当
exp
输入的头部分刚好导致结果溢出到无穷大时,尾部分可能是负数,因此
powf()
的结果实际上是有限的。解决这一问题的一种方法是在这种情况下将“head”的值减少1,另一种方法是在可用的情况下,通过舍入到零模式计算head,因为这将确保head和tail的符号相同。另一个警告是,如果指数运算确实溢出,我们无法插值结果,因为这样做会创建一个NaN

需要注意的是,这里使用的对数计算的精度不足以确保精确取整的
powf()
实现,但它提供了一个相当小的误差(我在广泛测试中发现的最大误差小于2 ULP)它允许代码保持合理的简单,以证明相关的设计原则

#包括//帮助函数,例如frexpf()、ldexpf()、isinff()、nextafterf()
/*具有扩展精度的计算日志(a),以双浮点值返回
洛基:洛基。最大相对误差约为8.36545e-10。
*/
作废我的日志(浮点a,浮点*loghi,浮点*loglo)
{
常量浮点LOG2_HI=0x1.62e430p-1f;//6.93147182e-1
常量浮点LOG2_LO=-0x1.05c610p-29f;/-1.90465421e-9
浮点数m,r,i,s,t,p,qhi,qlo;
INTE;
/*将[181/256,362/256]中的参数缩减为m*/
m=frexpf(a和e);
如果(m<0.70703125f){/*181/256*/
m=m+m;
e=e-1;
}
i=(浮点数)e;
/*将q=(m-1)/(m+1)计算为双浮点qhi:qlo*/
p=m+1.0f;
m=m-1.0f;
r=1.0f/p;
qhi=m*r;
t=fmaf(qhi,-2.0f,m);
s=fmaf(qhi,-m,t);
qlo=r*s;
/*近似atanh(q),q in[-75/437,53/309]*/
s=qhi*qhi;
r=0x1.08c000p-3f;//0.1292724609
r=fmaf(r,s,0x1.22cde0p-3f);/0.1419942379
r=fmaf(r,s,0x1.99a160p-3f);/0.2000148296
r=fmaf(r,s,0x1.555550p-2f);/0.3332539
t=fmaf(qhi,qlo+qlo,fmaf(qhi,qhi,-s));//s:t=(qhi:qlo)**2
p=s*qhi;
t=fmaf(s,qlo,fmaf(t,qhi,fmaf(s,qhi,-p));//p:t=(qhi:qlo)**3
s=fmaf(r,p,fmaf(r,t,qlo));
/*对数(a)=2*atanh(q)+i*log(2)*/
t=fmaf(LOG2_HI*0.5f,i,qhi);
p=fmaf(-LOG2_高*0.5f,i,t);
s=(qhi-p)+s;
s=fmaf(对数低*0.5f,i,s);
r=t+t;
*loghi=t=fmaf(2.0f,s,r);
*loglo=fmaf(2.0f,s,r-t);
}
/*计算exp(a)。最大ulp错误=0.86565*/
浮动my_expf_未选中(浮动a)
{
浮动f,r;
int i;
//exp(a)=exp(i+f);i=rint(a/log