问题
如何通过其他方法求解根号n—— n \sqrt{n} n
解决
梯度下降
梯度下降主要通过求梯度为0的点,得到凸函数的全局最小值。
首先构建损失函数为凸函数的目标函数,使得目标函数的最小值对应的是我们要求的值,即:
L = ( x 2 − n ) 2 = x 4 − 2 n x 2 + n 2 L=(x^2-n)^2=x^4-2nx^2+n^2 L=(x2−n)2=x4−2nx2+n2
这样就可以保证区间 ( 0 , + ∞ ) (0,+\infty) (0,+∞)上目标函数是凸函数,并且 n \sqrt{n} n处取最小值。
然后对其进行求导:
∇ x L = 4 x 3 − 4 n x = 4 x ( x 2 − n ) \nabla_x L=4x^3-4nx=4x(x^2-n) ∇xL=4x3−4nx=4x(x2−n)
然后给定一个初始值 x 0 x_0 x0和学习率 α \alpha α,梯度下降过程就是:
x n + 1 = x n − α ∇ x L x_{n+1}=x_n-\alpha \nabla_x L xn+1=xn−α∇xL
通过判断 α ∇ L \alpha \nabla L α∇L的精确度可以得到不同精确度的结果
python实现:
import random
def sqrt(n):
alpha=0.001
x=random.uniform(0,n/2.)
delta=n
# 差需要不大于0.001才行,即精确度为小数点后2位
while abs(delta)>0.001:
delta=4*x*(x**2-n)
x-=alpha*delta
return x
牛顿迭代
我们要求 x 2 − C x^2-C x2−C的零点,可以随机初始化一个点 ( x i , x i 2 − C ) (x_i,x_i^2-C) (xi,xi2−C),该点要大于 C \sqrt{C} C,然后计算该点处切线的方程,找到其与x轴的交点作为 x i + 1 x_{i+1} xi+1,依次类推。
这里使用C而不是n。
对于 ( x i , x i 2 − C ) (x_i,x_i^2-C) (xi,xi2−C),切线的斜率,即梯度为 2 x i 2x_i 2xi,直线方程为 y = 2 x i ( x − x i ) + x i 2 − C y=2x_i(x-x_i)+x_i^2-C y=2xi(x−xi)+xi2−C,其与x轴交点为 ( 1 2 ( x i + C x i ) , 0 ) (\frac{1}{2}(x_i+\frac{C}{x_i}),0) (21(xi+xiC),0),所以更新公式为:
x i + 1 = 0.5 ∗ ( x i + C x i ) x_{i+1}=0.5*(x_i+\frac{C}{x_i}) xi+1=0.5∗(xi+xiC)
def sqrt(n):
res=n/2.
next=0.5*(res+n/res)
while abs(res-next)>0.001:
res=next
next=0.5*(res+n/res)
return res
袖珍计算器算法
通过一定的转化:
n = n 1 2 = e 1 2 ln n \sqrt{n}=n^{\frac{1}{2}}=e^{\frac{1}{2}\ln n} n=n21=e21lnn
所以可以这样计算:
def sqrt(n):
import math
return math.exp(0.5*math.log(n))
二分查找
就是简单的查找,这里使用LeetCode 69的设置,求整数
def sqrt(n):
left,right=0,n
res=n
while left<=right:
mid=(left+right)//2
if mid*mid<=n:
res=mid
left=mid+1
else:
right=mid-1
return res