牛顿迭代法

如果我们想求一个正整数a的平方根,那么,我们可以把它转换为方程

x2a=0

方法一:二分

那么,我们首先想到的就是二分法,用二分来解决这个问题(在一定的精度下),每次都找到上次取的中间值。直到与答案的差值在需要的精度之内。

不过,二分法有一个缺点,那就是需要的次数很多。如果要求出更精确的值,那么就要迭代很多次,很费时间。

那么,有没有更快的方法呢?

方法二:牛顿迭代法

如果我们以2为例,那么这时,a就等于2,我们可以把它看成一个函数。f(x)=x22。那么,我们可以发现,我们要求的就是f(x)=0的时候,x的值。这时,我们可以从2开始迭代。

那么,该如何做到最快速的迭代呢?

肯定是按照函数的切线去迭代。

那么,我们发现,f(x)的导数是f(x)=4x6,然后,就可以一直推导下去。效率是每推一次,就能增加3位的精度,效率比二分法好了不少.

代码:

#include<cmath>
#include<iomanip>
#include<cassert>
#include<iostream>
#define endl "\n"
using namespace std;

/*牛顿迭代
float newton(int x){
    if(x==0){
        return 0;
    }
    return sqrt(x,x);
}

float sqrt(float i,int x){
    float res=(i+x/i)/2;
    if(res==i){
        return i;
    }
    else{
        return sqrt(res,x);
    }
}
*/

float q_sqrt(float x){//求sqrt(x)
    float xhalf=0.5f*x;
    int i=*(int*)&x;
    i=0x1fbd1df5+(i>>1);
    x=*(float*)&i;
    for(int r=0; r<10; r++){
        x=0.5f*x+xhalf/x;
    }
    return x;
}

float Q_rsqrt(float number){//求1/(sqrt(number))
    long i;
    float x2,y;
    const float threehalfs=1.5F;
    x2=number*0.5F;
    y=number;
    i=*(long*)&y;
    i=0x5f3759df-(i>>1);
    y=*(float*)&i;
    for(int r=0; r<10; r++){
        y=y*(threehalfs-(x2*y*y));//迭代
    }
#ifndef Q3_VM
#ifdef __linux__
    assert(!isnan(y));
#endif
#endif
    return y;
}

int main(){
    float n;
    cin>>n;
    cout<<Q_rsqrt(n)<<endl;
    cout<<q_sqrt(n)<<endl;
    return 0;
}

posted @   lwr2010  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示