动态输出n位小数——满满都是坑!

【题目描述】

输入正整数abc,输出a/b的小数形式,精确到小数点后c位。a,b ≤10^6 ,c≤100。输入包含多组数据,结束标记为abc=0。

【样例输入】

1 6 4

0 0 0

【样例输出】

Case 1: 0.1667

【题目来源】

刘汝佳《算法竞赛入门经典  第2版》习题2-5 分数化小数(decimal)

【解析】

这道题很简单呀!

等等,以前都是题目中明确给出保留几位小数,比如要求保留3位小数,咱们就可以:

printf(“%.3f”, a/b);

本题要保留的小数位数是在程序运行时指定的,取决于用户输入的c,这该怎么办呢?难不成要写成这样:

printf(“%.%df”, c, a/b);

实际测试完全行不通,看来格式说明符是不能嵌套的。这其实很好理解,如果支持嵌套,不光看起来乱,还会导致歧义。比如%%df,按理%%应解释为转义字符,用来表示字符“%”。

一、用系统函数动态输出n位小数

1.C语言版

这里涉及一个新的语法知识点,要实现按变量的值动态输出小数位数,就要把代码改成这样子:

printf(“%.*f”, c, a/b);

*和f一样,也是一个占位符,起占位作用,它表示从参数中取一个整数值来作为浮点数的精度。

学会了这种操作,代码马上呼之欲出:

#include<stdio.h>
int main(){int a, b, c, kase=0;while(scanf("%d%d%d", &a, &b, &c)==3 && a*b*c){double f = (double)a/b;printf("Case %d: %.*f\n", ++kase, c, f);}return 0;
}

输入样例测试也满全符合,是不是大功告成了呢?

2. C++版

除了上面的C语言版,也可以使用纯C++语法动态输出小数位数(语法非常麻烦)。

#include <iostream>
#include <iomanip> // 包含 setprecision 的头文件
using namespace std;
int main() {int a, b, c, kase=0;while(scanf("%d%d%d", &a, &b, &c)==3 && a*b*c){double f = (double)a/b;cout << "Case " << ++kase << ": " << fixed << setprecision(c) << f << endl;}return 0;
}

遗憾的是,咱们费了半天劲儿,上面的面代码却都是错误的。

重点就在于题目要求c≤100,如果输入1 6 100,马上就会发现输出结果不正确。

测试是非常重要的,尤其是边界数据的测试更为重要。

因为double的有效精度只有16位,因而用printf根本无法有效输出100位小数。

怎么办呢?自己动手,丰衣足食。

二、自己动手算小数

咱们要用程序模拟小数除法运算,想想小学时学的运算规则:每次求出的余数后添0,然后继续除。比如28÷16:

算法可以描述为:

①求商的整数部分。

②求商的小数部分:重复将余数乘10继续除。

这就完了吗?别忘了“精确到小数点后c位”的意思?最后一位输出的小数需要四舍五入。

代码如下:

#include<stdio.h>
int main(){int a, b, c, kase=0;while(scanf("%d%d%d", &a, &b, &c)==3 && a*b*c){//输出小数点前的内容printf("Case %d: %d.", ++kase, a/b);//输出小数点后的c-1位a=a%b;for(int i=1; i<=c-1; i++){a*=10;printf("%d", a/b);a = a%b; //获取第i位运算后的余数}//输出第c位小数,四舍五入a*=10;printf("%d", a/b + 10*(a%b)/b/5);printf("\n");}return 0;
}

四舍五入部分当然也可以用If语句判断第c+1位小数的值是否大于等于5,这里用了一个巧算,用n/5即可实现当n≥5时,结果为1。

这回终于结束了吧!

No,No,No,客官即将迎来本题的最大深坑。

如果输入下面的数据,就知道上面的代码问题出在哪了。

999 1000 2

9999 1000 2

输出结果:

因为小数部分有一连串的9,进位会导致前面的小数甚至整数全部改变,因而按照上面的代码就会输出错误结果。

如果给咱9999/1000这道算术题,让咱保留两位小数,咱肯定不会算错。但是让咱设计保留2位小数的算法,就非常容易忽略这种情况。前者是看到某种情形,想到对应规则,后者是想到所有情形,想到对应规则,难度不可同日而语。

所以算法设计必须要穷尽所有可能性,遗漏任何一种情形都会导致出错。对于数据来讲,最容易被忽略的就是边界数据。

比如本题,小数位数100位是边界,最后一位小数要四舍五入是边界,9进位会变成0也是边界(9是最大数字)。因此,对于任何类型的数据,一定要养成思考边界、测试边界的习惯。

三、用数组解决999式进位问题

要解决这个问题,就需要用到数组,把每位小数都存到数组中,再根据各位小数值及是否要进位重新修正每位小数的值。

代码如下:

#include<stdio.h>
int main(){int a, b, c, point, d[105], kase=0;while(scanf("%d%d%d", &a, &b, &c)==3 && a*b*c){//求出小数点后的c+1位int r=a%b;for(int i=1; i<=c+1; i++){r*=10;d[i] = r/b;r%=b; //获取第i位运算后的余数}//根据是否进位修正各位小数d[0] = 0; //保存小数到整数的进位if(d[c+1] >= 5){for(int i=c; i>=0; i--){if(9 == d[i]){d[i] = 0;} else{d[i] += 1;break;}}}//输出小数点前的内容printf("Case %d: %d.", ++kase, a/b + d[0]);//输出小数部分for(int i=1; i<=c; i++){printf("%d", d[i]);}printf("\n");}return 0;
}

需要说明的是,本题是第2章习题,此章节还没学到数组,但这道题目前老金只会用数组求解。如有高人知道不用数组的解法,还望指点一二!

最后总结一下,这道题非常容易出错,它有三大神坑:

①用printf函数最多只能输出16位有效小数,无法输出100位,必须要自己模拟除法运算求小数。

②最后一位小数需要根据下一位小数四舍五入。

③最后一位小数如果是9,在四舍五入时会导致前面的小数发生变化,如果有一连串的9,可能会使所有小数甚至整数部分都产生变化。这是本题最大的坑,可谓神之一坑。

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

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

相关文章

填字母游戏【蓝桥杯】/博弈+dfs

填字母游戏 博弈dfs #include<iostream> #include<map> using namespace std; //要用map存储已经处理过的字符串不然会超时 map<string,int> m; //dfs返回的就是结果 int dfs(string s) {//剪枝if(m.find(s)!m.end()) return m[s];//找到LOL代表输了if(s.fi…

显示学习1(基于树莓派Pico) -- 基础

先上图为敬。 驱动的是0.96寸的OLED&#xff0c;SSD1315。使用的I2C接口驱动。 有一说一树莓派Pico用来学习底层真的太好了&#xff0c;没有之一。首先是价格便宜&#xff0c;10块钱包邮还要什么自行车。然后底层封装很完备&#xff0c;接近闭源。最后是用的python&#xff0c…

使用nodejs搭建脚手架工具并发布到npm中

使用nodejs搭建脚手架工具并发布到npm中 一、安装环境依赖及脚手架搭建过程二、搭建Monorepo 风格的脚手架工程三、脚手架的必备模块命令参数模块获取命令参数设置子命令用户交互模块文件拷贝模块脚手架中的路径处理目录守卫文件拷贝模块动态文件生成模块mustache简介自动安装依…

思迈特软件与上海德拓签署战略合作协议,携手赋能企业数字化转型

3月27日&#xff0c;广州思迈特软件有限公司&#xff08;简称“思迈特软件”&#xff09;与上海德拓信息技术有限公司&#xff08;简称“德拓信息”&#xff09;正式签约建立战略合作伙伴关系。双方将在数字化转型、数据服务、数据应用以及市场资源等多个领域展开深度合作&…

基于机器学习的信用卡办卡意愿模型预测项目

基于机器学习的信用卡办卡意愿模型预测项目 在金融领域&#xff0c;了解客户的信用卡办卡意愿对于银行和金融机构至关重要。借助机器学习技术&#xff0c;我们可以根据客户的历史数据和行为模式预测其是否有办理信用卡的倾向。本项目通过Python中的机器学习库&#xff0c;构建…

高频SQL 有趣的电影

题目信息 表&#xff1a;cinema -------------------------- | Column Name | Type | -------------------------- | id | int | | movie | varchar | | description | varchar | | rating | float | --------------------…

CSS变换

CSS变换 根据 CSS 的变换的功能特性&#xff0c;它可以分为位移、旋转、缩放、倾斜和透视&#xff1a; 也可以分成2D变换和3D变换&#xff0c;2D变换是二维平面上进行的&#xff0c;即 X 轴和 Y 轴。这些变换不涉及 Z 轴。3D 变换允许元素在三维空间中进行操作&#xff0c;这些…

Spring WebFlux响应式实现WebFilter解决跨域问题

WebFilter 是 Spring Framework 中用于处理 Web 请求的过滤器接口&#xff0c;它是在基于 Servlet 3.0 规范的基础上&#xff0c;为了支持响应式编程模型而引入的。与传统的 Servlet 过滤器相似&#xff0c;WebFilter 也允许开发者对进入的请求和返回的响应进行拦截、修改或者增…

SQL SERVER 备份

目录 1.备份概念 1.1 为何备份? 1.2 SQL Server 备份模式 2.SQL Server 数据库备份 2.1 借助SSMS备份数据库 2.2 借助 T-SQL 备份数据库 2.3 创建加密备份 2.4 备份文件和文件组 权限 步骤 2.5 备份事务日志 3.维护计划 3.1 完整备份 3.2 差异备份

谈谈Python中的生成器表达式和它们的优势

谈谈Python中的生成器表达式和它们的优势 生成器表达式是Python中一个非常强大且高效的功能&#xff0c;它允许我们以一种简洁而直观的方式创建生成器对象。生成器表达式与列表推导式&#xff08;list comprehensions&#xff09;非常相似&#xff0c;但它们在内存使用和执行方…

初学ELK - elk部署

一、简介 ELK是3个开源软件组合&#xff0c;分别是 Elasticsearch &#xff0c;Logstash&#xff0c;Kibana Elasticsearch &#xff1a;是个开源分布式搜索引擎&#xff0c;提供搜集、分析、存储数据三大功能。它的特点有&#xff1a;分布式&#xff0c;零配置&#xff0c;自…

为什么说基于贫血模型的MVC架构违背OOP

我们大部分的业务开发都是MVC架构的&#xff0c;但是我们平时使用的基于贫血模型的MVC架构它对吗&#xff1f;为了搞清楚这个问题&#xff0c;我们先来理清楚几个概念。 一、贫血模型VS充血模型 贫血模型与充血模型是软件开发中两种常见的设计模式&#xff0c;它们各自具有独…

如何进行Python代码的调试和测试?

如何进行Python代码的调试和测试&#xff1f; Python代码的调试和测试是软件开发过程中不可或缺的一部分&#xff0c;它们确保代码的正确性、可靠性和性能。下面将详细讨论如何进行Python代码的调试和测试。 一、Python代码调试 调试是查找并修复代码错误的过程。Python提…

大学英语ab级题搜题软件?分享7个支持答案和解析的工具 #笔记#其他

合理利用学习辅助工具和资料&#xff0c;可以帮助大学生更好地组织学习内容、掌握知识点和提升学术水平。 1.智能翻译官 这是一款多语言在线翻译神器&#xff0c;除了最基础的英语以外&#xff0c;还支持日语、德语、俄语、法语等几十种语言文本翻译和拍照翻译&#xff0c;并…

面试算法-148-轮转数组

题目 给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 示例 1: 输入: nums [1,2,3,4,5,6,7], k 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1,2,3,4,5,6] 向右轮转 2 步: [6,7,1,2,3,4,5] 向右轮转 3 步: [5,6,7,…

php代码执行计划任务dos实现方式和宝塔面板实现方式

dos php 计划任务 echo off :loop echo 这是一个死循环 echo This is an infinite loop. php think gpt php think ai timeout /t 2 goto loop 宝塔面板 php 计划任务 #!/bin/bash PATH/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin export PATH ste…

蓝桥杯刷题--python38

197. 阶乘分解 - AcWing题库 def init(n): for i in range(2,n1): if not st[i]:primes.append(i) j0 while primes[j]*i<n: st[i*primes[j]]1 if i%primes[j]0: break j1 nint(input(…

关于Ansible模块 ⑤

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 继《关于Ansible的模块 ①》、《关于Ansible的模块 ②》与《关于Ansible的模块 ③》之后&#xff0c;继续学习ansible常用模块之…

如何利用Flutter将应用成功上架至iOS平台:详细指南

引言 &#x1f680; Flutter作为一种跨平台的移动应用程序开发框架&#xff0c;为开发者提供了便利&#xff0c;使他们能够通过单一的代码库构建出高性能、高保真度的应用程序&#xff0c;同时支持Android和iOS两个平台。然而&#xff0c;完成Flutter应用程序的开发只是第一步…

医院要不要安装医疗设备漏费控费管理系统

19339904493&#xff08;康溪&#xff09; 不知道大家有没有去医院做过检查&#xff0c;比如说做B超、彩超、多普勒、胃肠镜、心电、脑电&#xff0c;核磁、CT、DR、X光、钼靶、生化分析仪、血球等。你们可能不知道&#xff0c;在做检查、检验的时候还会存在一个漏洞。医院的存…