我已经发布了几个小时前关于牛顿方法的问题,我得到了答案,并希望感谢大家,现在我已经尝试实现代码本身
#include <iostream>
#include <math.h>
using namespace std;
#define h powf(10,-7)
#define PI 180
float funct(float x){
return cos(x)-x;
}
float derivative (float x){
return (( funct(x+h)-funct(x-h))/(2*h));
}
int main(){
float tol=.001;
int N=3;
float p0=PI/4;
float p=0;
int i=1;
while(i<N){
p=p0-(float)funct(p0)/derivative(p0);
if ((p-p0)<tol){
cout<<p<<endl;
break;
}
i=i+1;
p0=p;
if (i>=N){
cout<<"solution not found "<<endl;
break;
}
}
return 0;
}
但是我写了输出“找不到解决方案”,在n = 3的三次迭代后的书中,它找到了这个.7390851332
的解决方案,所以我的问题是我应该多么小的改变h或者我该如何改变我的这样的代码,得到正确的答案?
答案 0 :(得分:2)
有几件事:
derivative
功能中的破坏性取消。你正在减去两个彼此非常接近的数字,因此差异会失去很多精确度。要扩展最后一点,一般方法是在值收敛时减少h
。但正如我在上一个问题中所提到的,这种“调整”h
方法基本上(代数)减少为正割方法。
答案 1 :(得分:1)
你只允许2次迭代,这可能不足以接近答案。如果您只有1个正确的位可以启动,那么在2次迭代后,您最多可以获得大约4个好位。你正在寻找10位精度(0.001大约是1/2 ^ 10),你必须允许至少2次迭代。
此外,二次收敛属性仅在您接近解决方案时才成立。当你离开时,接近解决方案可能需要更长的时间。
使用中心差计算数值导数的最优h是单精度(浮点数)的0.005 * max(1,| x |),其中| x |是参数x的绝对值。对于双精度,它大约是5e-6 * max(1,| x |)。
答案 2 :(得分:1)
如果你的h太小,那么由于浮点舍入,你的导数将是不准确的。您的代码将受益于使用双精度而不是单精度,尤其是当您通过有限差分进行区分时。使用双精度,你的h值就可以了。如果坚持单精度,则需要使用更大的值。
仅允许2次迭代似乎相当严格。使N更大并让程序打印出所使用的迭代次数。
此外,无需使用战俘。只需写1e-7。