看来你的任务是计算
⎛ xN ⎞(aN / aD)
⎜⎼⎼⎼⎼⎟ where xN,xD,aN,aD ∈ ℤ, xD,aD ≠ 0
⎝ xD ⎠
仅使用乘法、除法、加法和减法,建议使用牛顿法。
我们试图求解的方程(对于y)是
(aN / aD)
y = (xN / xD) where y ∈ ℝ
牛顿法找到函数的根。如果我们想用它来解决上面的问题,我们从左边减去右边,得到一个函数,其零给我们想要的y :
(aN/aD)
f(y) = y - (xN/xD) = 0
帮助不大。我想这就是你得到的?这里的重点是暂时不要形成该函数,因为我们没有办法计算有理数的有理幂!
首先,让我们确定aD和xD都是正数。如果aD为负,我们可以简单地通过否定aN和aD来做到这一点(因此aN / aD的符号不会改变),如果xD为负,则同时否定xN和xD。请记住,根据定义,xD或aD都不是零。然后,我们可以简单地将两边都提高到aD次方:
aD aN aN aN
y = (xN / xD) = xN / xD
我们甚至可以通过将两边都乘以最后一项来消除除法:
aD aN aN
y × xD = xN
现在,这看起来很有希望!我们从中得到的功能是
aD aN aN
f(y) = y xD - xN
牛顿法也需要导数,这显然是
f(y) aD aN
⎼⎼⎼⎼ = df(y) = y xD y / aD
dy
牛顿方法本身依赖于迭代
f(y)
y = y - ⎼⎼⎼⎼⎼⎼
i+1 i df(y)
如果你算出数学,你会发现迭代只是
aD
y[i] y[i] xN
y[i+1] = y[i] - ⎼⎼⎼⎼ + ⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼
aD aD aN
aD y[i] xD
您不需要将所有y值保存在内存中;记住最后一个就足够了,当它们的差异足够小时就停止迭代。
您仍然有上面的幂运算,但现在它们只是整数幂运算,即
aD
xN = xN × xN × .. × xN
╰───────┬───────╯
aD times
您可以非常简单地做到这一点,例如只需将参数乘以所需的次数,例如在 C 中,
double ipow(const double base, const int exponent)
{
double result = 1.0;
int i;
for (i = 0; i < exponent; i++)
result *= base;
return result;
}
有更有效的方法来进行整数求幂,但是上面的函数应该是完全可以接受的。
最后一个问题是选择初始y以便收敛。您不能使用 0,因为(的幂)y用作除法中的分母;你会得到零误差除法。就个人而言,我会检查结果是否应该是正数或负数,以及小于或大于 1 的数量级;总体上有两条规则来选择一个安全的初始y。
问题?