计算C中的小数指数

use*_*097 2 c exponent newtons-method

我正在尝试评估一个^ n,其中a和n是有理数.我不想使用任何预定义的功能,如sqrt()pow()

所以我试图使用牛顿方法来使用这种方法得到近似解:

3 ^ 0.2 = 3 ^(1/5),因此如果x = 3 ^ 0.2,则x ^ 5 = 3.

解决这个问题的最佳方法(没有计算器,但仍然使用基本的算术运算)可能是使用"牛顿法".用于求解方程f(x)= 0的牛顿方法是建立一个数字序列xn,其定义为将x0作为一些初始"猜测"然后xn + 1 = xn-f(xn/f'(xn)其中f '(x)是f的导数.

发表于物理论坛

该方法的问题在于,如果我想计算5.2^0.33333,我需要找到这个方程的根x^10000 - 5.2^33333 = 0.我结束了庞大的数字,并获得infnan错误的大部分时间.

有人可以就如何解决这个问题给我建议吗?或者,有人可以提供另一种算法来计算^ n吗?

Nom*_*mal 7

看来你的任务就是计算

? xN ?(aN / aD)
??????           where xN,xD,aN,aD ? ?,  xD,aD ? 0
? xD ?
Run Code Online (Sandbox Code Playgroud)

仅使用乘法,除法,加法和减法,使用牛顿方法作为建议的实现方法.

我们试图解决的等式(对于y)是

             (aN / aD)
y = (xN / xD)            where y ? ?
Run Code Online (Sandbox Code Playgroud)

牛顿的方法找到函数的根.如果我们想用它来解决上面的问题,我们从左侧减去右侧,得到一个零,它给出了我们想要的y:

                  (aN/aD)
f(y) = y - (xN/xD)        = 0
Run Code Online (Sandbox Code Playgroud)

没什么帮助.我想这就是你得到的?这里的要点是暂时还没有形成这个功能,因为我们没有办法计算有理数的理性幂!

首先,让我们确定aDxD都是正数.如果aD为负,那么我们可以简单地通过否定aNaD来做到这一点(因此aN/aD的符号不会改变),如果xD为负,则否定xNxD.请记住,根据定义,xDaD都不为零.然后,我们可以简单地提高双方在公元次方":

 aD            aN     aN     aN
y   = (xN / xD)   = xN   / xD
Run Code Online (Sandbox Code Playgroud)

我们甚至可以通过将双方乘以最后一个术语来消除分裂:

 aD     aN     aN
y   × xD   = xN
Run Code Online (Sandbox Code Playgroud)

现在,这看起来很有前途!我们从中获得的功能是

        aD   aN     aN
f(y) = y   xD   - xN
Run Code Online (Sandbox Code Playgroud)

牛顿的方法也需要衍生物,这显然是必然的

f(y)            aD   aN
???? = df(y) = y   xD   y / aD
 dy
Run Code Online (Sandbox Code Playgroud)

牛顿方法本身依赖于迭代

             f(y)
y    = y  - ??????
 i+1    i    df(y)
Run Code Online (Sandbox Code Playgroud)

如果你计算出数学,你会发现迭代就是这样

                                 aD
                y[i]      y[i] xN
y[i+1] = y[i] - ???? + ??????????????
                 aD           aD   aN
                       aD y[i]   xD
Run Code Online (Sandbox Code Playgroud)

您不需要将所有y值保留在内存中; 它足以记住最后一个,并在它们的差异足够小时停止迭代.

你仍然有上面的取幂,但现在它们只是整数取幂,即

  aD
xN   = xN × xN × .. × xN
       ?????????????????
              aD times
Run Code Online (Sandbox Code Playgroud)

你可以非常简单地做,例如只需将参数乘以所需的次数,例如在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;
}
Run Code Online (Sandbox Code Playgroud)

有更有效的方法可以进行整数求幂,但上述函数应该是完全可以接受的.

最后一个问题是选择初始y以便收敛.你不能使用0,因为(幂的)y被用作分区中的分母; 你会得到零除错误.就个人而言,我会检查结果应该是正面的还是负面的,小于或大于一个; 两个规则总体上选择一个安全的初始y.

有问题吗?