寻找完全平方数——浮点数陷阱

【题目描述】

输出所有形如aabb的4位完全平方数(即前两位数字相等,后两位数字也相等)。

【解析】

一、问题分析

从问题出发,题目要求输出的是满足一定条件的数。数在计算机中是要占存储空间的,要在计算机中表示一个数,一定要考虑它的数据类型、数据长度。这里是4位整数,所以用int数据类型就可以了。

如果把数看成一个对象,它也有自己的属性和方法。

二、已知条件分析

1. 已知条件转化为隐含条件。

本题对要输出的数给定了3个已知条件:

(1) 形如aabb(即前两位数字相等,后两位数字也相等)。注意括号内对aabb的解释,只要求前两位相等,后两位也相等,对ab是否相等未作要求。题目未作要求,就是没有限制,就是怎样都可以。所以不要看写着形如aabb就想当然地以为a、b要是不同的两个数。a、b只是两个字母,是未知数,在未给定条件时,它可以是任意数。

(2) 4位数。一个数是几位数是从最左侧的第一个非0数开始计算,比如0123既不是4位数,也不是3位数,因为它根本不是数。所以本题要求是4位数,a的值不能为0。也就是a的取值范围是1-9,b的取值范围是0-9。

(3)完全平方数。完全平方数(perfect square)指能表示成某个整数的平方的数。例如,0、1、4、9都是完全平方数,因为它们分别是0、1、2、3的平方。根据定义可知,完全平方数是非负整数。

2. 隐含条件转换为数学表达式。

仅仅将已知条件转化为隐含条件还不够,还要进一步转化为数学表达式,才可能将其转化为代码。

上述三个条件中主要涉及的数学表达式是aabb这个数表示,它可以表示成:a*1100 + b*11

三、算法分析

本题的本质是从一定范围的整数中找出一些符合特殊条件的整数,所以可以用“穷举法”。

穷举法的穷举范围极大地影响程序的效率,所以要尽量缩小穷举的范围。

本题的穷举范围和符合条件判断有两种:

①大范围:4位数→缩小范围:4位数+形如aabb的数(无法进一步缩小),符合条件:完全平方数。

②大范围:4位数→缩小范围:4位数+完全平方数(无法进一步缩小),符合条件:形如aabb

下面分别阐述两种算法。

1. 遍历范围:4位形如aabb的数,符合条件:完全平方数

这个4位数用aabb表示,前面讨论过,a的取值范围是1-9,b的取值范围是0-9。也就是说a取的每一位数字,都要与b取的0-9组合一遍,就像相亲节目中每个男生都会用目光欻欻歘歘朝着每个女生闪烁一遍。每个男生一个接一个上台轮流闪烁,这是一次循环;每个男生上台后闪烁对面一个接一个的女生,又是一次循环。所以程序要用到循环的嵌套:循环里面套循环。

程序主干如下:

for(int a = 1; a <= 9; a++)for(int b = 0; b <= 9; b++)if(aabb是完全平方数) printf("%d\n", aabb);

这段主干程序并不是合法的C程序,第三行代码是不符合语法规范的,因而无法运行。

这样的不能真正运行的简化代码称为伪代码(pseudocode)。伪代码主要用于描述算法梗概,避开细节,启发思路。在使用伪代码时,可以不必拘泥格式,只求简明即可。

这段伪代码完整地表现出了程序的三个部分:遍历、判断、输出。

上述伪代码要变成真正的代码,需要解决两个问题:

(1) aabb的表示。

C语言中是无法用aabb这样的形式输出数的,因为它会被编译器识别为变量。把伪代码改写成代码时,一般先选择较为容易的任务来完成。前面讲过,这个问题比较简单,只要用a*1100 + b*11这种表达式的形式表示即可。

(2) 判断aabb是否为完全平方数。

这还不简单吗?只要用sqrt()函数给aabb开平方,再判断结果是不是一个整数不就行了?

这是正向思维,这个思路的难点在于,sqrt()函数的返回值是double类型,这种浮点数是有误差的。这意味着如果它的返回值是0.9999999999,它的真实值可能是一个整数1。

所以咱们是不能用下面这种方式来进行判断的:

if(sqrt(aabb)==最接近sqrt(aabb)的整数)printf("%d\n", aabb);

要判断一个浮点数是不是整数,只能用一个不太完美的办法:求这个浮点数与最接近它的值的整数的差,如果这个差小于一个很小的数,就认为它是整数。

那这个很小的数应该是多大合适呢?

系统为咱们定义了名叫DBL_EPSILON的宏,定义在头文件<float.h>中。它就是那个很小的正数,用于处理浮点数精度问题。DBL是double的缩写。EPSILON是希腊语,代表第五个希腊字母ε。ε在数学中常被用来表示一个非常小的正数,这个数可以任意小,但不等于零。

代码如下:

#include<stdio.h>#include<math.h>#include <float.h>int main(){for(int a = 1; a <= 9; a++)for(int b = 0; b <= 9; b++){int aabb = a*1100 + b*11; //这里才开始使用n,因此在这里定义ndouble r1 =  sqrt(aabb);int r2 = floor(r1 + 0.5);if(fabs(r1 - r2) < DBL_EPSILON) printf("%d\n", aabb);}return 0;}

注意sqrt(aabb)后面加上0.5这个细节,这是为了在转化为整数时进行四舍五入。函数floor(x)返回不超过x的最大整数。这里floor(sqrt(aabb) + 0.5)其实也可以写成:int r = (int)(sqrt(aabb) + 0.5)。后者是用数据类型强制转换的方式,舍去小数部分。它和用floor函数有什么区别呢?读者可以猜想一下。

fabs(x)返回x的绝对值。

虽然用上述代码也能输出正确的结果,但不能改变它是个天生残疾的事实。而且如果你忘了或不知道那个很小的数的宏名更当如何呢?

换一种思路,用逆向思维,就能避开浮点数误差,找到完美的算法:求出最接近sqrt(aabb)的整数,反过来判断它的平方是否等于aabb。

代码如下:

#include<stdio.h>#include<math.h>int main(){for(int a = 1; a <= 9; a++)for(int b = 0; b <= 9; b++){int aabb = a*1100 + b*11; //这里才开始使用n,因此在这里定义nint r = floor(sqrt(aabb) + 0.5);if(r*r == aabb) printf("%d\n", aabb);}return 0;}

2. 遍历范围:4位完全平方数,符合条件:形如aabb

这种方法天生具有完美基因,因为它不涉及浮点数。

整数开方会产生小数,整数的平方只能是整数。

#include<stdio.h>int main(){for(int x = 1; ; x++){int aabb = x * x;if(aabb < 1000) continue;if(aabb > 9999) break;int hi = aabb / 100;int lo = aabb % 100;if(hi/10 == hi%10 && lo/10 == lo%10) printf("%d\n", aabb);}return 0;}

continue和break语句是C语言的两个语句。continue的作用是跳过当前循环体中剩余未执行的语句,并立即开始下一次的循环条件判定,即执行下一次循环。break的作用是直接跳出循环,即立即结束整个循环。

两种算法都介绍完了,问题来了,哪个算法效率更高呢?你猜猜!

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

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

相关文章

L1-035 情人节

以上是朋友圈中一奇葩贴&#xff1a;“2月14情人节了&#xff0c;我决定造福大家。第2个赞和第14个赞的&#xff0c;我介绍你俩认识…………咱三吃饭…你俩请…”。现给出此贴下点赞的朋友名单&#xff0c;请你找出那两位要请客的倒霉蛋。 输入格式&#xff1a; 输入按照点赞…

C语言字符串型常量

在C语言中&#xff0c;字符串型常量是由一系列字符组成的常量。字符串常量在C中以双引号&#xff08;"&#xff09;括起来&#xff0c;例如&#xff1a;“Hello, World!”。字符串常量在C中是不可变的&#xff0c;也就是说&#xff0c;一旦定义&#xff0c;就不能修改其内…

Web自动化测试流程:从入门到精通,帮你成为测试专家

摘要&#xff1a; Web应用程序在今天的软件开发中占据着越来越重要的地位。保证Web应用程序的质量和稳定性是非常必要的&#xff0c;而自动化测试是一种有效的方法。本文将介绍Web自动化测试流程&#xff0c;并提供代码示例。 步骤一&#xff1a;选取测试工具 选择适合自己团…

探讨代理IP在大数据收集、网络营销中的战略角色

代理IP在大数据收集和网络营销中扮演着至关重要的战略角色&#xff0c;其主要体现在以下几个方面&#xff1a; 1. 避免IP限制与反爬机制&#xff1a; - 在大数据收集过程中&#xff0c;尤其是网络爬虫抓取数据时&#xff0c;目标网站通常会设置访问频率限制或IP封锁策略以防止恶…

Linux作业调度和服务管理

目录 作业调度 调整进程的优先级 服务管理 systemd管理服务操作 systemd管理target&#xff08;一点点&#xff09; 作业调度的本质仍然是进程&#xff0c;之所以叫做作业调度&#xff0c;作业是以shell为单位的&#xff0c;一个shell建立的作业&#xff0c;不会被另外一个…

12 数据库安全和管理

文章目录 数据库安全和管理表的复制数据库备份MySQL远程连接添加用户和授权 数据库安全和管理 表的复制 表能根据实际需求复制数据复制表时不会把KEY属性复制过来 语法 create table 表名 select 查询命令;create table student select name,age,score from class where sc…

像SpringBoot一样使用Flask - 5.统一处理(日志、异常、响应报文)

接上文《像SpringBoot一样使用Flask - 4.拦截器》&#xff0c;通过拦截器处理一些日志&#xff0c;异常、还有统一的响应报文。 统一的目的就是为了让前后端调用请求不会因为各自习惯而随意编写&#xff0c;增加技术人员快速上手及代码的可阅读性。 一、定义一个返回类。是不是…

ZigBee技术与实践教程(持续更新笔记)

1.安全性 802.15.4 在数据传输过程中提供了三级安全性。 &#xff08;1&#xff09;第一级实际是无安全性方式&#xff0c;对于某种应用&#xff0c;如果安全性并不重要或者上一层已经提供了安全性保护&#xff0c;器件就可以采用这种方式来转移数据。 &#xff08;2&#x…

(已解决)报错:Could not load the Qt platform plugin “xcb“

完整报错信息 QObject::moveToThread: Current thread (0x6a879f0) is not the object’s thread (0x61bb590). Cannot move to target thread (0x6a879f0)qt.qpa.plugin: Could not load the Qt platform plugin “xcb” in “” even though it was found. This application…

深入了解 Python 的 compile() 函数

在 Python 中&#xff0c;compile() 是一个内置函数&#xff0c;用于将字符串形式的 Python 代码编译为可执行的代码对象&#xff0c;或者将 AST&#xff08;抽象语法树&#xff09;对象编译为代码对象。本文将深入探讨 compile() 函数的用法、参数和返回值&#xff0c;以及其在…

【Java】使用`LinkedList`类来实现一个队列,并通过继承`AbstractQueue`或者实现`Queue`接口来实现自定义队列

使用LinkedList类来实现一个队列&#xff0c;并通过继承AbstractQueue或者实现Queue接口来实现自定义队列。 以下是一个简单的示例&#xff0c;其中队列的大小与另一个List的容量保持一致&#xff1a; import java.util.LinkedList; import java.util.List; import java.util…

网络安全运营的工作内容(附资料下载)

【推荐】最新网络安全运营方案和实践合集&#xff08;共80多份&#xff09;.zip 网络安全运营的工作内容是一个多层次、多维度的体系&#xff0c;涵盖了多个关键领域以确保网络环境的稳定和安全。以下是一些主要的工作内容&#xff1a; 安全策略制定与实施&#xff1a; 制定网…

【前端Vue】Vue从0基础到大神完整教程第1篇:vue基本概念,vue-cli的使用【附代码文档】

Vue从0基础到大神学习完整教程完整教程&#xff08;附代码资料&#xff09;主要内容讲述&#xff1a;vue基本概念&#xff0c;vue-cli的使用&#xff0c;vue的插值表达式&#xff0c;{{ gaga }}&#xff0c;{{ if (obj.age > 18 ) { } }}&#xff0c;vue指令&#xff0c;综合…

20行代码搞定PDF表格转为Excel表

1.环境准备 安装好python并且配置好环境安装pdfplumber、xlwt库使用Vscode或者PyCharm等编辑器 在pycharm中如果报红&#xff0c;可以鼠标点击报红的库&#xff0c;altenter进行安装 2.代码部分 import pdfplumber import xlwt # 读取源pdf文件 pdf pdfplumber.open("…

2024-2030年再生混凝土市场供给规模及投资策略战略规划报告

2024-2030年再生混凝土市场供给规模及投资策略战略规划报告 《报告编号》: BG475174 《出版时间》: 2024年3月 《出版机构》: 中智正业研究院 《交付方式》: EMIL电子版或特快专递 《报告价格》:【纸质版】: 6500元 【电子版】: 6800元 【纸质电子】: 7000元 《 免费售后 服务…

图像处理ASIC设计方法 笔记8 卷积计算芯片的结构

(一) P81 卷积芯片内部模板框图 该设计有两个数据通路:图像数据和模板数据。 图像数据是经过帧控制、实时图SPRAM(写控制、 SPRAM读控制、数据读控制)、计算单元; 模板数据是经过模板SPRAM、计算单元。 4.5.4运算单元像素寄存器控制 存储SPRAM写入的64bit数据,输出为…

Unity2023.1.19_DOTS_JobSystem

Unity2023.1.19_DOTS_JobSystem 上篇我们知道了DOTS是包含Entity Component System&#xff0c;Job System&#xff0c;Burst compiler三者的。接下来看下JobSystem的工作原理和具体实现。 简介&#xff1a; 官方介绍说&#xff1a;JobSystem允许您编写简单而安全的多线程代…

C++篇 语 句

到目前为止&#xff0c;我们只见过两种语句&#xff1a; return 语句和表达式语句。根据语句对执行顺 序的影响&#xff0c;C 语言其余语句大多属于以下 3 大类。 选择语句&#xff1a; if 语句和 switch 语句。循环语句&#xff1a; while 语句&#xff0c; do...while 语句和…

XSS漏洞-存储型漏洞案例

一、环境 在github上找DVWA的靶机环境 DVWA存储库 二、复现 先将其安全等级改为低 然后点击存储型的xss&#xff0c;先随便写几条看看现象 可以看到我们写的都展示在了下面的框中 看看源码&#xff0c;分析在存储时的漏洞 我们可以看到&#xff0c;在对数据插入的时候&am…

01_04_JavaWEB01_HTMLCSS

一 HTML入门 参考尚硅谷再总结复习 1.1 HTML&CSS&JavaScript的作用 HTML 主要用于网页主体结构的搭建 CSS 主要用于页面元素美化 JavaScript 主要用于页面元素的动态处理 1.2 什么是HTML HTML是Hyper Text Markup Language的缩写。意思是超文本标记语言。它的作用是搭…