平方根(sqrt)算法

18 篇文章 0 订阅
7 篇文章 0 订阅

最近听说开平方算法挺难写,自己思考一下确实这些库函数只是一直在用,但是很少去思考如何实现的,sqrt在排序中使用频率非常的高,所以就研究了一下。大概有三种实现方式。

一、用二分的方法

        每次用中间数就试,如果大就到左区间选取中间数试,如果小就到右区间找中间数试,采用不断逼近的方式计算平方根,这种方式迭代次数有点多,且每次试验都要进行运算,效率不是很高,但是思路简单,巧妙的运用了二分的方法。

#define eps 0.00000001
float SqrtByBisection(float n)
{
    //小于0的按照你需要的处理
    if(n < 0)
        return n;
    float mid,last;
    float low,up;
    low=0,up=n;
    mid=(low+up)/2;
    do
    {
        if(mid*mid>n)
            up=mid;
        else
            low=mid;
        last=mid;
        mid=(up+low)/2;
    }
    //精度控制
    while(fabs(mid-last) > eps);
    return mid;
}
二、牛顿迭代法

这种方式的原理就是通过f(x) = x^2 - a = 0 的切线来逼近x^2 -a =0的的根,根号a就是f(x) =0的一个正实根,这个函数的导数是2x,也就是切线的斜率是2x,也就是x-f(x)/2x是比x更接近的近似值,带人方程得到f(x) = (x+a/x) / 2是更近似的值

float SqrtByNewton(float x)
{
 float val = x;//最终
 float last;//保存上一个计算的值
 do
 {
  last = val;
  val =(val + x/val) / 2;
 }while(fabs(val-last) > 0.0001);
 return val;
}
三、神一样的算法
float InvSqrt(float x)
{
 float xhalf = 0.5f*x;
 int i = *(int*)&x; // get bits for floating VALUE
 i = 0x5f3759df - (i>>1); // gives initial guess y0
 x = *(float*)&i; // convert bits BACK to float
 x = x*(1.5f-xhalf*x*x); // Newton step, repeating increases accuracy
 return x;
}

这个算法是卡马克(quake3作者)实现的,他真正牛B的地方是他选择了一个神秘的常数0x5f3759df 来计算那个猜测值,也是采用牛顿迭代法,但是选择的常数是绝妙的,能降上面的牛顿迭代法效率提高四倍,有空一定要拜读一下quake3的源代码,我在资源中放了一份 欢迎下载

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Verilog中的平方根算法可以使用牛顿迭代法来实现。下面是一个使用牛顿迭代法计算平方根的Verilog代码示例: ```verilog module sqrt_calculator ( input wire [31:0] x, output reg [15:0] sqrt ); reg [15:0] next_sqrt; reg [47:0] diff; always @(x or sqrt) begin next_sqrt = sqrt; diff = (next_sqrt * next_sqrt) - x; if (diff > 0) begin next_sqrt = next_sqrt - 1; diff = (next_sqrt * next_sqrt) - x; end while (diff < 0) begin next_sqrt = next_sqrt + 1; diff = (next_sqrt * next_sqrt) - x; end sqrt = next_sqrt; end endmodule ``` 在这个示例中,我们使用了一个输入端口 `x`,用于指定要计算平方根的数值。输出端口 `sqrt` 将给出计算得到的平方根值。 在 `always` 块中,我们定义了一个迭代过程来逐步逼近平方根。首先,我们将当前的 `sqrt` 值赋给 `next_sqrt`。然后,我们计算 `next_sqrt` 的平方,并将其与输入值 `x` 进行比较,得到 `diff`。 如果 `diff` 大于零,则说明 `next_sqrt` 的平方超过了 `x`,需要将 `next_sqrt` 减一,以使其平方小于或等于 `x`。然后,我们再次计算新的 `diff` 值。 接下来,我们使用一个循环来逐步增加 `next_sqrt` 的值,直到 `diff` 大于或等于零为止。这样,我们就得到了最接近输入值 `x` 的平方根。 最后,我们将计算得到的平方根值赋给输出端口 `sqrt`。 请注意,这只是一个简单的示例,可能存在精度或性能方面的改进空间,具体实现取决于您的需求和资源限制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值