草庐IT

「浙江理工大学ACM入队200题系列」问题 B: 零基础学C/C++12——求平均值

孤星·璀璨 2023-03-28 原文

本题是浙江理工大学ACM入队200题第二套中的B题

我们先来看一下这题的题面.


由于是比较靠前的题目,这里插一句.各位新ACMer朋友们,请一定要养成仔细耐心看题的习惯,尤其是要利用好输入和输出样例.

  • 样例相当于给你举了个具体的例子,可以帮助你更好的理解题目
  • 样例会告诉你输入和输出的格式,你必须要在程序里以这样的格式输入和输出,否则会出问题
  • 样例可以在你本地写完代码之后用作测试,来检查你的代码能否正常地运行(不过样例运行正确并不代表完全对了,可能输入其他的数据会出现别的问题)

题面

题目描述

输入3个整数,求出平均值,保留3位小数

输入

输入3个整数

输出

输出平均值,保留3位小数

样例输入

2 3 4

样例输出

3.000

常见错误思路

这题看起来非常简单,相信每一位朋友看完题面以后都会有一下的思路:

  1. 从输入流读入这3个整数
  2. 根据平均值的定义,先把3个整数加起来,然后除以3
  3. 将算得的结果以3位小数的格式输出(什么,你说你不会保留3位小数?先往下看后面会给出的)

于是有些朋友们给出了如下的代码(局部):

int sum = a + b + c; // 利用sum变量保存三整数和
double ave = sum / 3; // 根据平均值的定义,计算平均值
printf("%.3lf", ave); // 利用printf函数输出结果(lf前的.3表示只显示3位小数,类似的显示两位就写%.2lf,简单吧)

发现能成功通过样例,于是自信满满地提交了上去,然后迎接他的是答案错误.

可是,难道平均值不是这么求的嘛?这和数学上求解平均值的方法完全一致啊,哪里会出现问题呢?

问题就出在这些朋友完全用数学来理解C语言的运算符了.当我们把输入改成2 2 4的时候,你就会发现程序的输出是2.000而不是我们所期待的2.666.

常见错误原因解析

首先,我们明白在C中,每个数据都是具有数据类型的,比如1,2,3这种的数据类型是int,而1.1,1.0这种的数据类型是double,并且在C中各个数据类型之间还是有一定的界限的,int和double还是有一定区别的,但是我们可以对它们进行类型转换:

  • int可以转为double,此时会在原本的整数之后补上全为0的小数部分
  • double可以转为int,此时会直接去掉原本实数的小数部分,只剩下整数部分(不是四舍五入,也不是向下取整,而是直接去掉)

然后,我们回到这道题来,为何2 2 4的输出是2.000呢?稍加观察不难发现,我们的错误结果正好是正确答案的整数部分.而后面的小数部分非常像int转为double时出现的全为0的小数部分.

那么,导致此处错误的真相也已然呼之欲出了,我们写的sum / 3所得的结果是int类型(由此才只有正确答案的整数部分),随后我们把它赋值给double类型的ave变量,触发了自动转型,将其变为了一个double类型的实数,也就是我们看到的2.000了.

那为何会如此呢?这是因为在C中,除法运算符所得结果的类型是两个操作数中精度最高的类型,精度顺序大致如下:

double > long long > int > short > char

当我们将一个int型的数据去除另一个int型的数据时,根据上述类型决定规则,我们得到的结果是一个int型的数据,由此导致了上述的问题.

这个问题在实际写代码中还是比较容易犯的,一不小心就会失误直接将两个int类型的数据相除,所以各位朋友们一定要注意奥!

解决方案

明白了问题所在,如何解决呢?非常简单,既然返回的是精度最高的类型,那么我们就将其中一个数据改为double类型呗,此处有多种解决方法:

  • double ave = (double)sum / 3; // 利用强制转型运算符将第一个操作数转为double

  • double ave = sum * 1.0 / 3; // 通过乘法(其结果类型决定方式与除法一致)间接将第一个操作数转为double(注意优先级问题,不要写成sum / 3 * 1.0)

  • double ave = sum / 3.0; // 将常数3写成实数形式

  • double sum = a + b + c; // 直接将sum定义为double类型

  • ...

上述几种方法在此处均可行,但在别的地方受限于具体情况可能只能使用其中的一种或几种,最好都理解并掌握(原理都是将一个操作数改为double类型)

参考代码

下面给出了我自己做这道题时候的完整代码:
(仅作为参考,一定要自己写一下奥,作弊没意思,害人又害己)

#include <stdio.h>

int main()
{
	int a, b, c; // 定义三个变量以储存输入的三个数
	scanf("%d%d%d", &a, &b, &c); // 输入三个数
	int sum = a + b + c;// 利用sum变量保存三整数和
	double ave = sum / 3.0; // 根据平均值的定义,计算平均值,并使结果为实数
	printf("%.3lf", ave); // 利用printf函数输出结果(lf前的.3表示只显示3位小数,类似的显示两位就写%.2lf,简单吧)
	
	return 0;
}

"正是我们每天反复做的事情,最终造就了我们,优秀不是一种行为,而是一种习惯" ---亚里士多德

这篇题解就到这里了,各位朋友如果有问题欢迎到acm成员群中提问哦!

有关「浙江理工大学ACM入队200题系列」问题 B: 零基础学C/C++12——求平均值的更多相关文章

  1. 深度学习12. CNN经典网络 VGG16 - 2

    深度学习12.CNN经典网络VGG16一、简介1.VGG来源2.VGG分类3.不同模型的参数数量4.3x3卷积核的好处5.关于学习率调度6.批归一化二、VGG16层分析1.层划分2.参数展开过程图解3.参数传递示例4.VGG16各层参数数量三、代码分析1.VGG16模型定义2.训练3.测试一、简介1.VGG来源VGG(VisualGeometryGroup)是一个视觉几何组在2014年提出的深度卷积神经网络架构。VGG在2014年ImageNet图像分类竞赛亚军,定位竞赛冠军;VGG网络采用连续的小卷积核(3x3)和池化层构建深度神经网络,网络深度可以达到16层或19层,其中VGG16和VGG

  2. 华为OD机试真题 C++ 实现【带传送阵的矩阵游离】【2023 Q2 | 200分】 - 2

            所有题目均有五种语言实现。C实现目录、C++实现目录、Python实现目录、Java实现目录、JavaScript实现目录题目n行m列的矩阵,每个位置上有一个元素你可以上下左右行走,代价是前后两个位置元素值差的绝对值.另外,你最多可以使用一次传送阵(只能从一个数跳到另外一个相同的数)求从走上角走到右下角最少需要多少时间。输入描述:第一行两个整数n,m,分别代表矩阵的行和列。后面n行,每行m个整数,分别代表矩阵中的元素。输出描述:一个整数,表示最少需要多少时间。

  3. ruby-on-rails - 无法构建 gem native 扩展 (mkmf (LoadError)) - Ubuntu 12.04 - 2

    这个问题在这里已经有了答案:Unabletoinstallgem-Failedtobuildgemnativeextension-cannotloadsuchfile--mkmf(LoadError)(17个答案)关闭9年前。嘿,我正在尝试在一台新的ubuntu机器上安装rails。我安装了ruby​​和rvm,但出现“无法构建gemnative扩展”错误。这是什么意思?$sudogeminstallrails-v3.2.9(没有sudo表示我没有权限)然后它会输出很多“获取”命令,最终会出现这个错误:Buildingnativeextensions.Thiscouldtakeawhi

  4. ruby - 使用 OpenSSL ruby​​ 从一个 .p12 文件中提取多个 key - 2

    我想知道如何从Apple.p12文件中提取key。根据我有限的理解,.p12文件是X504证书和私钥的组合。我看到我遇到的每个.p12文件都有一个X504证书和至少一个key,在某些情况下有两个key。这是因为每个.p12都有一个Apple开发人员key,有些还有一个额外的key(可能是Appleroot授权key)。我只考虑那些具有两个key的.p12文件是有效的。我的目标是区分具有一个key的.p12文件和具有两个key的.p12文件。到目前为止,我已经使用OpenSSL来检查X504文件和任何.p12的key。例如,我有这段代码可以检查目录中的所有.p12文件:Dir.glob(

  5. ruby-on-rails - Rails 在记录 200 OK 后在做什么? (调试响应时间慢) - 2

    我试图在我的RubyonRails应用程序中调试一个极其缓慢的请求调用。我已设法根据自己的喜好优化Controller方法,Rails的日志告诉我它已在XX毫秒内完成操作(Completed200OKin5049ms(Views:34.9ms|ActiveRecord:76.3ms)).但是,在加载页面时,在浏览器中实际呈现任何内容之前打印此消息很长;最多约15秒的等待时间。Rackmini-profiler证实了这一点,告诉我GET操作(不计算完成Controller操作所花费的时间)花费了14秒左右。(分析器还确认Controller操作的执行时间约为5秒)。我可以接受Contro

  6. ruby-on-rails - Rails Controller 中未定义的方法呈现 - 尝试使用 200 状态代码响应 Sendgrid - 2

    我正在使用SendgridParseAPI和Griddlergem来接受传入的电子邮件。在大多数情况下,这工作正常;但是,如果您未使用状态代码200响应Sendgrid,他们将假定该应用程序未正确接收POST请求并继续尝试进行POST3天。我正在尝试使用状态代码进行响应,但遇到了问题。在常规的RESTful路由中,您可以执行类似...render:status=>200但是,我认为这必须在Controller中完成才能识别渲染方法。Griddler建议您创建一个EmailProcessor模型并使用“处理”方法来处理电子邮件。据我了解,您不能在模型中使用渲染方法。因此,我使用类方法创建

  7. ruby - 为什么 openssl 在 windows 上产生错误但在 centos 上不产生错误:PKCS12_parse: mac verify failure (OpenSSL::PKCS12::PKCS12Error) - 2

    require'openssl'ifARGV.length==2pkcs12=OpenSSL::PKCS12.new(File.read(ARGV[0]),ARGV[1])ppkcs12.certificateelseputs"Usage:load_cert.rb"end运行它会在Windows上产生错误,但在Linux上不会。错误:OpenSSL::PKCS12::PKCS12Error:PKCS12_parse:macverifyfailurefrom(irb):21:ininitializefrom(irb):21:innewfrom(irb):21fromC:/Ruby192/

  8. ruby-on-rails - macOS 10.12 Sierra 上的 bundle 错误 - 2

    Ignoringbinding_of_caller-0.7.2becauseitsextensionsarenotbuilt.Try:gempristinebinding_of_caller--version0.7.2Ignoringbyebug-9.0.6becauseitsextensionsarenotbuilt.Try:gempristinebyebug--version9.0.6Ignoringcapybara-webkit-1.11.1becauseitsextensionsarenotbuilt.Try:gempristinecapybara-webkit--versio

  9. NEUQ-acm 预备队训练Week4—BFS/DFS - 2

    1.深度优先搜索(DFS)深度优先遍历主要思路是从图中一个未访问的顶点V开始,沿着一条路一直走到底,然后从这条路尽头的节点回退到上一个节点,再从另一条路开始走到底…,不断递归重复此过程,直到所有的顶点都遍历完成。例题P1605迷宫题目描述给定一个N×MN\timesMN×M方格的迷宫,迷宫里有TTT处障碍,障碍处不可通过。在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。给定起点坐标和终点坐标,每个方格最多经过一次,问有多少种从起点坐标到终点坐标的方案。输入格式第一行为三个正整数N,M,TN,M,TN,M,T,分别表示迷宫的长宽和障碍总数。第二行为四个正整数SX,S

  10. ruby - 如何在 ubuntu 12.0.4 上将 usr/local/bin 添加到路径环境变量? - 2

    我刚刚在Ubuntu12.0.4上安装了ruby​​.1.8.6。我正在从一本书中学习ruby​​,在安装过程之后它说"Onceit'scompleted,youshouldadd/usr/local/bintoyourPATHenvironmentvariable.I'llassumethat,beingaLinuxuser"我被困住了,因为这个人的假设是错误的。如何将usr/local/bin添加到路径环境变量中? 最佳答案 您可以将此添加到您的~/.bashrc文件中:PATH=$PATH:/usr/local/bin如果你不

随机推荐