基于牛顿法的开平方实现

引言

牛顿法是求解最优问题的一种常用方法。

方法简述

本文主要在实现使用牛顿法进行开平方操作,代码使用python实现。在开平方求解中,更多的可以参考这篇文章。牛顿法是一种最优化求解方法,在迭代过程中求取到最接近解的值,类似的还有梯度下降等等。

方法分析

这里主要讲解我对该方法的推导,有错误之处麻烦指出。
首先针对开根号求解,可用以下式子描述:
x = n x=\sqrt{n} x=n
将该式换成:
x 2 = n x^{2}=n x2=n
移项得
x 2 − n = 0 x^{2} - n = 0 x2n=0
要求出n的开跟结果,其实就是求出该式的解,对于该式,可以描述为:
x 2 − n = y x^{2} - n = y x2n=y
也就是求出该抛物线与x轴的交点,因为实数范围内求出的开根号结果大于0,因此只需要计算大于零的一边。对于该式的求解,牛顿法的迭代速度较快。
在这里插入图片描述
图中,首先给定初始的值,这个值可以随便给,图中选的是x=4,如红色竖线所示。牛顿法的精髓就在于,给定初始值之后,能够快速下降到目标解。在x=4这一点,获取该点的切线,如图紫色斜线所示。求出该点切线与x轴交点即为下次迭代的x值,最后迭代多次之后,如果在误差范围内,输出结果。
令给定一个初始值 x 1 x_{1} x1
在式中:
x 2 − n = y x^{2} - n = y x2n=y
其对应的点为 ( x 1 , x 1 2 − n ) (x_{1},x_{1}^{2} - n) (x1,x12n),该点对应的斜率为 2x1,斜率公式为:
2 x = y 2x = y 2x=y
斜率公式可通过对x求导得出。将点和斜率带入斜线公式:
a x + b = y ax+b=y ax+b=y
求得下一个迭代的点为:
x 2 = − b a = n 2 x 1 + x 1 2 x_{2}=\frac{-b}{a}=\frac{n}{2x_{1}}+\frac{x_{1}}{2} x2=ab=2x1n+2x1
迭代多次,知道求出 x n − x n − 1 &lt; δ x_{n}-x_{n-1}&lt;\delta xnxn1<δ δ \delta δ为自定的误差范围。

代码如下:

def SquareRoot(n):
    tx = 100
    lstx = tx
    for i in range(10):
        tx = (n / tx / 2 + tx / 2)
        if (abs(tx - lstx) < 0.0000001):
            break
        lstx = tx
    return tx

测试了本方法与系统自带方法运算效率:
在这里插入图片描述
可能是因为python的原因,结果虽然正确,但是时间上时系统自带方法的两倍。但是就算如此,该方法也比二分法好。

GitHub Link:https://github.com/ThisskyMain/MyAlgorithm

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Verilog是一种硬件描述语言,用于描述数字电路的行为和结构。牛顿迭代法是一种数值计算方法,用于求解方程的近似解。牛顿迭代法开平方是利用牛顿迭代法来计算一个数的平方根。 在Verilog中实现牛顿迭代法开平方,可以按照以下步骤进行: 1. 定义输入和输出信号:根据需要,定义一个输入信号表示待开平方的数,以及一个输出信号表示计算得到的平方根。 2. 初始化变量:定义一个变量作为初始猜测值,可以选择待开平方数的一半作为初始值。 3. 迭代计算:使用牛顿迭代法进行迭代计算,直到满足停止条件。迭代公式如下: ``` guess = (guess + number/guess) / 2; ``` 其中,guess表示当前的猜测值,number表示待开平方的数。 4. 判断停止条件:可以选择设置一个误差范围,当当前猜测值与上一次猜测值之间的差小于误差范围时,停止迭代。 5. 输出结果:将最终计算得到的平方根值赋给输出信号。 下面是一个简单的Verilog代码示例: ```verilog module NewtonSquareRoot( input wire [31:0] number, output wire [15:0] sqrt ); reg [15:0] guess; reg [15:0] next_guess; reg [15:0] error; initial begin guess = number >> 1; // 初始猜测值为待开平方数的一半 error = 16'hFFFF; // 设置一个初始误差范围 end always @(posedge clk) begin next_guess = (guess + (number / guess)) >> 1; // 迭代计算新的猜测值 error = guess - next_guess; // 计算当前猜测值与上一次猜测值之间的差 guess <= next_guess; // 更新猜测值 end assign sqrt = guess; // 将最终计算得到的平方根赋给输出信号 endmodule ``` 请注意,上述代码仅为示例,具体实现可能需要根据具体需求进行调整和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值