Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 牛顿&x2013;当一个函数几乎为“0”时,拉斐逊方法是不可能的;“平坦”;_C++_Math_Double_Numeric - Fatal编程技术网

C++ 牛顿&x2013;当一个函数几乎为“0”时,拉斐逊方法是不可能的;“平坦”;

C++ 牛顿&x2013;当一个函数几乎为“0”时,拉斐逊方法是不可能的;“平坦”;,c++,math,double,numeric,C++,Math,Double,Numeric,我正在尝试计算x^x的值。 我已经计算了它的导数,我是 使用牛顿-拉斐逊法求给定a的f(x)=x^x-a的根。 这是我用来计算下一个近似值的函数: double xkp1(double xk, double a){ double lnxp1 = log(xk) +1; return xk -( (fx(xk, a)) / (exp(xk*log(xk)) * (log(xk) + 1) )); } 其中,函数fx的定义如下: double fx(double x, dou

我正在尝试计算x^x的值。
我已经计算了它的导数,我是
使用牛顿-拉斐逊法求给定a的f(x)=x^x-a的根。

这是我用来计算下一个近似值的函数:

double xkp1(double xk, double a){
    double lnxp1 = log(xk) +1;
    return xk -( (fx(xk, a))  /  (exp(xk*log(xk)) * (log(xk) + 1)  ));
}
其中,函数fx的定义如下:

double fx(double x, double a){
    return exp(x*log(x))-a;
}
现在,只有当xk的起始值已经接近根时,这种方法才能正常工作。
如果它相差+-0.5,xk就爆炸到一个非常高的值,f(x)变成无穷大。
现在我想这里可能有什么问题-x^x的导数与x^x的实际值相比非常小,所以整个
(fx(xk,a))/(exp(xk*log(xk))*(log(xk)+1))
变成+无穷大-切线超出了根。

这意味着我需要更高的双精度,但有可能吗?如果没有,可以修改方法中的某些内容以使其适用于这种情况吗?

我假设您只对正
x
值感兴趣,而不是负整数(也有实数)

我有两个解决方案可以帮助你解决你的问题。首先,如果首先使用对数变换,数值格式可能更稳定。然后,您的等式将是找到
a
,这样
x log(x)=log(a)
x log(x)
的导数是
log(x)+1
,它可能比指数函数更稳定

否则,您可以使用您所知道的
f(x)=x^x
x>1/e
上单调递增来运行对分搜索。从
x_l=1/e
x_r=2/e
开始。如果
f(x_l)>a
,则没有解决方案。然后,当
f(x_r)
时,设置
x_l=x_r
x_r=c*x_r
(或增加
x_r
的任何其他方案)。一旦你有了一对紧跟在
f(x\u l)
之后的
x\u l,x\u r
,你就可以开始对分搜索,找到一个包含
f(x)=a的解的小区间。一旦这个间隔足够小,你就可以从牛顿方法的迭代开始了


您甚至可以将上述两种方法结合起来,执行对分搜索,以求解
x log(x)=log(a)

您对
a
的测试值是多少?另外,您可以取两边的对数,然后解出
x*log(x)=log(a)
——远不太可能过冲,最终得到天文值。