平方根的三种求法(袖珍计算器算法,二分查找,牛顿迭代)

news2024/7/31 1:59:01

一、袖珍计算器

袖珍计算器方法主要运用到了我们高数上所学的关于e底数转化的思想,即

一种用指数函数 exp⁡ 和对数函数 ln⁡ 代替平方根函数的方法 :

1、exp函数:

exp是 C 标准库 <math.h> 中的一个函数,用于计算 e 的 x 次幂,其中 e 是自然对数的底数(约为 2.71828)。

函数声明:

#include <math.h>

double exp(double x);
float expf(float x);
long double expl(long double x);

函数用法:

#include <stdio.h>
#include <math.h>

int main ()
{
   double x = 0;
  
   printf("e 的 %lf 次幂是 %lf\n", x, exp(x));
   printf("e 的 %lf 次幂是 %lf\n", x+1, exp(x+1));
   printf("e 的 %lf 次幂是 %lf\n", x+2, exp(x+2));
   
   return(0);
}

 2、log函数:

log是 C 标准库 <math.h> 中的一个函数,用于计算一个浮点数的自然对数(以 e 为底)。

函数声明:

#include <math.h>

double log(double x);
float logf(float x);
long double logl(long double x);

函数返回值:

  • 如果 x 为负数,log() 函数将返回 NaN,并设置 errno 为 EDOM
  • 如果 x 为零,log() 函数将返回 -HUGE_VAL(负无穷大),并设置 errno 为 ERANGE

C 库宏 extern int errno 是通过系统调用设置的,在错误事件中的某些库函数表明了什么发生了错误。

errno 是 C 标准库中的一个宏,定义在 <errno.h> 头文件中。它用于指示在程序运行过程中发生的错误。errno 实际上是一个整数变量,用于存储错误代码。库函数在发生错误时,会设置 errno 为适当的错误代码,以便程序可以检查和处理这些错误。

函数用法:

#include <stdio.h>
#include <math.h>

int main ()
{
   double x, ret;
   x = 2.7;

   /* 计算 log(2.7) */
   ret = log(x);
   printf("log(%lf) = %lf", x, ret);
   
   return(0);
}

3、实现

所以我们可以写出如下的函数:

int mySqrt(int x) {
        if (x == 0) {
            return 0;
        }
        int ans = exp(0.5 * log(x));
        return ans;

}

但是在leetcode上提交会有一项通不过:

由于计算机无法存储浮点数的精确值,而指数函数和对数函数的参数和返回值均为浮点数,因此运算过程中会存在误差。例如当 x=2147395600的计算结果与正确值 463404634046340 相差 10^-11 ,这样在对结果取整数部分时,会得到 463394633946339 这个错误的结果。因此在得到结果的整数部分后,我们应当再将(ans+1)^2的值再与x经行比较如果比x小则说明出现了刚刚那种情况。

二、二分查找

这种思想主要是来源于对于x的平方根ans(平方根的整数部分)来说:ans^2一定是<=x的,

(ans+1)^2>x

所以一种简单的思想是将从0到x的所有值与x按照上面的思路比较


    int mySqrt(int x) {
        unsigned long long len=0;
        unsigned long long ret=0;
        while(len<=x)
        {
            if(len*len<=x&&(len+1)*(len+1)>x)
            {
                ret=len;
                break;
            }
            len++;
        }
        return ret;

    }

但是实际上我们比较的时候是相当于对有序数组经行查找操作,所以我们可以用二分查找的想法去改进这个题:

int mySqrt(int x) 
{
    int l = 0, r = x, ans = -1;
    while (l <= r) {
        long long  mid = l + (r - l) / 2;
        if (mid * mid <= x) {
            ans = mid;
            l = mid + 1;
        }
        else {
            r = mid - 1;
        }
    }
    return ans;

}

 三、牛顿迭代

1、原理

牛顿迭代法是一种可以用来快速求解函数零点的方法。(链接:牛顿迭代法_百度百科 (baidu.com))我们可以设出如下函数:

 显然:c的平方根计算f(x)的零点(零点是x的值,这里我们取正的);

牛顿迭代法的本质是借助泰勒级数,从初始值开始快速向零点逼近。我们任取一个xo作为初始值,在每一步的迭代中,我们找到函数图像上的点(xi,f(xi)),过该点作一条斜率为该点导数f'(xi)的直线,与横轴的交点记为xi+1。xi+1相较于xi而言距离零点更近。在经过多次迭代后,我们就可以得到一个距离零点非常接近的交点。

按照我的理解就是利用函数切点斜率等于函数值变化率的 本质使得f(xo)的值快速往下降最终降到为0时即为零点。

2、算法

我们选择xo=C作为初始值。
在每一步迭代中,我们通过当前的交点xi,找到函数图像上的点(xi,x²-C),作一条斜率为f'(xi)=2x;的直线,直线的方程为:
                                                y=2xi*(x-xi)+xi²-C
                                                  =2xi*x-(x²+C)

横轴的交点为方程2xi*x-(xi²+C)=0的解,即为新的迭代结果xi+1=1/2*(xi+c/xi)
在进行k次迭代后,xk的值与真实的零点√C足够接近,即可作为答案。

什么时候结束呢?

一般来说,可以判断相邻两次迭代的结果的差值是否小于一个极小的非负数 ϵ,其中 ϵ 一般可以取 10^−6或 10^-7(再leetcode上这个数据段可以用1e-7来实现也可以看这篇博客:(C中float类型与0比较用e-7的原因_fabs(disc) <= 1e-7-CSDN博客)

3、实现:

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 (fabs(x0 - xi) < 1e-7) {
                break;
            }
            x0 = xi;
        }
        return int(x0);
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1870642.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Spring】SpringCloudAlibaba学习笔记

Nacos Nacos是一个更易于构建云原生应用的动态服务发现/服务配置和服务管理平台核心功能: 服务注册: Nacos Client会通过发送REST请求向Nacos Server注册自己的服务, 提供自己的元数据, 如ip地址/端口等信息; Nacos Server收到注册请求后, 就会把这些信息存储在Map中服务心跳:…

远程工具的使用

远程连接工具的作用&#xff0c;通过远程连接到服务器上&#xff0c;方便操作&#xff01; 1.常见的远程连接工具 XShell&#xff1a;这是一款Windows平台下的SSH客户端软件&#xff0c;支持SSH1、SSH2、SFTP、TELNET、RLOGIN等多种协议&#xff0c;功能丰富&#xff0c;包…

计算机二级Access操作题总结——综合应用

属性表相关 例1&#xff1a; 不允许输入和修改其中的数据→【是否锁定】 例2&#xff1a; 单击“退出”按钮(名为“bt2”)&#xff0c;调用设计好的宏“mEmp”来关闭窗体。 分组和汇总 对“rSell”报表进行适当设置&#xff0c;使每名雇员的姓名显示在该雇员所售书籍信…

Python学习笔记24:进阶篇(十三)常见标准库使用之数据压缩功能模块zlib,gzip,bz2,lzma的学习使用

前言 本文是根据python官方教程中标准库模块的介绍&#xff0c;自己查询资料并整理&#xff0c;编写代码示例做出的学习笔记。 根据模块知识&#xff0c;一次讲解单个或者多个模块的内容。 教程链接&#xff1a;https://docs.python.org/zh-cn/3/tutorial/index.html 数据压缩…

C语言的内存知识

这节我们主要认识一下内存&#xff0c;便于理解指针操作和后续内存管理。 一、内存分区模型 C程序在执行时&#xff0c;将内存大方向划分为4个区域 &#xff08;可以结合函数小节的函数栈帧部分看一下&#xff09; ⚪ 代码区:存放函数体的二进制代码&#xff0c;由操作系统进…

wgcloud怎么保证数据的安全性

WGCLOUD做了以下方面来保证数据安全 1、私有化部署 WGCLOUD是完全本地部署&#xff0c;没有云端服务&#xff0c;因此不用担心数据被他人获取 2、加密传输数据 WGCLOUD支持https传输数据&#xff0c;查看配置说明&#xff0c;实现使用SSL证书https访问server页面 - WGCLOUD…

第一后裔/The First Descendant延迟高的解决方法

第一后裔/The First Descendant是一款备受玩家关注的射击游戏&#xff0c;该作拥有多个角色&#xff0c;并为其设定不同的概念和战斗风格&#xff0c;以及技能点&#xff0c;不仅能让玩家畅快作战&#xff0c;还能通过各种道具&#xff0c;不断强化角色能力值&#xff0c;让其战…

Python 基础:使用 unittest 模块进行代码测试

目录 一、测试函数2.1 通过案例2.2 不通过案例2.3 添加新测试 二、测试类2.1 单个测试案例2.2 多个测试案例 三、总结 遇到看不明白的地方&#xff0c;欢迎在评论中留言呐&#xff0c;一起讨论&#xff0c;一起进步&#xff01; 本文参考&#xff1a;《Python编程&#xff1a;…

Jenkins教程-9-发送企业微信测试报告通知

上一小节我们学习了Jenkins上下游关联自动化测试任务的构建的方法&#xff0c;本小节我们讲解一下发送企业微信测试报告通知的方法。 1、自动化用例执行完后&#xff0c;使用pytest_terminal_summary钩子函数收集测试结果&#xff0c;存入本地status.txt文件中&#xff0c;供J…

Arathi Basin (AB) PVP15

Arathi Basin &#xff08;AB&#xff09; PVP15 阿拉希盆地&#xff0c;PVP&#xff0c;15人战场

【银河麒麟】高可用触发服务器异常重启,处理机制详解

1.服务器环境以及配置 【机型】物理机 处理器&#xff1a; Intel 内存&#xff1a; 126G 【内核版本】 4.19.90-25.16.v2101.ky10.x86_64 【银河麒麟操作系统镜像版本】 Kylin-Server-10-SP2-Release-Shenzhen-Metro-x86-Build01-20220619 Kylin-HA-10-SP2-Release-S…

前端vue3 根据某些Id 筛选数据

现在有一些不等的数据 我需要通过前端 吧这个数据筛选一下 比如我使用一些 我需要的ID 下的数据 比如以上的数据 的 cinemaLineId 来筛选 const cinemaLineId ref(["1246429254713147392", "1182608813770321920", "1182608917403185152"])…

大数据之Hadoop部署

文章目录 服务器规划服务器环境准备1. 网络测试2. 安装额外软件包3. 安装基础工具4. 关闭防火墙5. 创建用户并配置权限6. 创建目录并设置权限7. 卸载JDK8. 修改主机名9. 配置hosts文件10. 重启服务器 配置免密登录安装Java安装Hadoop1. Hadoop部署2. 配置Hadoop3. 格式化Hadoop…

【PyQt5】一文向您详细介绍 QVBoxLayout() 的作用

【PyQt5】一文向您详细介绍 QVBoxLayout() 的作用 下滑即可查看博客内容 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我静心耕耘深度学习领域、真诚分享知识与智慧的小天地&#xff01;&#x1f387; &#x1f393; 博主简介&#xff1a;985高校的普通本硕&a…

机器人控制系列教程之URDF文件语法介绍

前两期推文&#xff1a;机器人控制系列教程之动力学建模(1)、机器人控制系列教程之动力学建模(2)&#xff0c;我们主要从数学的角度介绍了机器人的动力学建模的方式&#xff0c;随着机器人技术的不断发展&#xff0c;机器人建模成为了机器人系统设计中的一项关键任务。URDF&…

我只有一点Python基础,对学习WebGIS开发有帮助吗?

经常有人后台私信问&#xff0c;我只有一点Python基础&#xff0c;对学习GIS开发有帮助吗&#xff1f; 关于这个问题的答案是&#xff0c;当然有&#xff01;Python适用于WebGIS开发。WebGIS是地理信息系统&#xff08;GIS&#xff09;技术与Web技术的结合&#xff0c;而Pytho…

Go语言学习:每日一练2

Go语言学习&#xff1a;每日一练2 目录 Go语言学习&#xff1a;每日一练2结构体零值数组切片映射指针 各个类型的零值一览 结构体 //定义 type Vertex struct {X, Y int } //使用 func main() { v1 : Vertex{1, 2} fmt.Println(v.X) //别的实例化方式 var v2 Vertex v2 : *new…

《PIDNet: A Real-time Semantic Segmentation Network Inspired by PID Controllers》

期刊&#xff1a;CVPR 年份&#xff1a;2023 代码&#xff1a;https://github.com/XuJiacong/PIDNet 摘要 双分支网络架构已经证明了它在实时语义分割任务中的有效性和有效性。然而&#xff0c;高分辨率细节和低频上下文的直接融合的缺点是细节特征很容易被周围的上下文信息…

Nuxt3 的生命周期和钩子函数(三)

title: Nuxt3 的生命周期和钩子函数&#xff08;三&#xff09; date: 2024/6/27 updated: 2024/6/27 author: cmdragon excerpt: 摘要&#xff1a;概述了Nuxt3的关键生命周期钩子用途&#xff0c;如page:finish用于页面加载后处理&#xff0c;page:transition:finish处理过…

MySQL数据库简介和安装

文章目录 一、数据库原理目前情况数据库的发展史RDBMS关系型数据库关系型数据库理论 二、MySQL历史发展历程关系型数据库和非关系型数据库 三、安装mysql及优化yum安装编译安装mysql二进制安装优化操作 四、 安装mycli插件客户端工具 一、数据库原理 目前情况 我们正处于一个…