求平方根

这篇博客介绍了使用指数函数和对数函数实现袖珍计算器求平方根的方法,以及牛顿迭代法快速求解平方根的原理。文章详细解释了为什么选择特定的初始值,并阐述了迭代结束的条件。最后,还提到了二分法作为另一种求解平方根的常见方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

袖珍计算器算法

【袖珍计算器】是一种使用【指数函数 e x p exp exp】和【对数函数 l n ln ln】代替平方根的方法。

x \sqrt{x} x = x 1 2 x^{\frac{1}{2}} x21 = ( e l n x ) 1 2 (e^{lnx})^{\frac{1}{2}} (elnx)21 = e 1 2 ln ⁡ x e^{\frac{1}{2} \ln x} e21lnx

注意: 由于计算机无法存储浮点数的精确值(浮点数的存储方法可以参考 IEEE 754,这里不再赘述),而指数函数和对数函数的参数和返回值均为浮点数,因此运算过程中会存在误差。例如当 x = 2147395600x=2147395600 时, e 1 2 ln ⁡ x e 1 2 ln ⁡ x e^{\frac{1}{2} \ln x}e^{\frac{1}{2}\ln x} e21lnxe21lnx的计算结果与正确值 46340 相差 1 0 − 11 10^{-11} 1011 ,这样在对结果取整数部分时,会得到 46339 这个错误的结果。

因此在得到结果的整数部分 ans \textit{ans} ans 后,我们应当找出 ans \textit{ans} ans ans + 1 \textit{ans} + 1 ans+1 中哪一个是真正的答案。

作者:LeetCode-Solution

class Solution {
    public int mySqrt(int x) {
        if (x == 0) {
            return 0;
        }
        int ans = (int) Math.exp(0.5 * Math.log(x));
        return (long) (ans + 1) * (ans + 1) <= x ? ans + 1 : ans;
    }
}

牛顿迭代法

牛顿迭代法式一种可以快速求解函数零点的方法。
设函数:
y = f ( x ) = x 2 − C y = f(x) = x^2-C y=f(x)=x2C
迭代 x i + 1 = 1 2 ( x i + C x i ) x_{i+1} = \frac{1}{2} (x_i + \frac{C}{x_i}) xi+1=21(xi+xiC)

细节
为什么选择 x 0 = C x_0 = C x0=C作为初始值?

  • 因为 y = x 2 − C y = x^2 - C y=x2C有两个零点 − C -\sqrt{C} C C \sqrt{C} C 如果我们取的初始值较小,可能会迭代到 − C -\sqrt{C} C 这个零点,而我们希望找到的是 C \sqrt{C} C 这个零点。因此选择 x 0 = C x_0 = C x0=C作为初始值,每次迭代均有 x i + 1 < x i x i + 1 x_{i+1} < x_ix i+1 xi+1<xixi+1,零点 C \sqrt{C} C 在其左侧,所以我们一定会迭代到这个零点。

迭代到何时才算结束?

  • 每一次迭代后,我们都会距离零点更进一步,所以当相邻两次迭代得到的交点非常接近时,我们就可以断定,此时的结果已经足够我们得到答案了。一般来说,可以判断相邻两次迭代的结果的差值是否小于一个极小的非负数 ϵ ϵ ϵ,其中 ϵ ϵ ϵ 一般可以取 1 0 − 6 10^{-6} 106 1 0 − 7 10^{-7} 107

如何通过迭代得到的近似零点得出最终的答案?

  • 由于 y = f ( x ) 在 [ C , + ∞ ] y = f(x) 在 [\sqrt{C}, +\infty] y=f(x)[C ,+] 上是凸函数(convex function)且恒大于等于零,那么只要我们选取的初始值 x 0 x_0 x0大于等于 C \sqrt{C} C ,每次迭代得到的结果 x i x_i xi都会恒大于等于 C \sqrt{C} C 。因此只要 \epsilonϵ 选择地足够小,最终的结果 x k x_k xk只会稍稍大于真正的零点 C \sqrt{C} C 。在题目给出的 32 位整数范围内,不会出现下面的情况:

真正的零点为 n − 1 / 2 ϵ n - 1/2ϵ n1/2ϵ,其中 n 是一个正整数,而我们迭代得到的结果为 n + 1 / 2 ϵ n+1/2ϵ n+1/2ϵ。在对结果保留整数部分后得到 n,但正确的结果为 n - 1。

作者:LeetCode-Solution

class Solution {
    public int mySqrt(int x) {
        if (x == 0) {
            return 0;
        }

        double C = x, x0 = x;
        while (true) {
            double xi = 0.5 * (x0 + C / x0);
            if (Math.abs(x0 - xi) < 1e-7) {
                break;
            }
            x0 = xi;
        }
        return (int) x0;
    }
}

二分法

比较简单常用不做赘述。

温故知新 未央书斋

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ambrosedream

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值