本题是浙江理工大学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. 「浙江理工大学ACM入队200题系列」问题 E: 零基础学C/C++78——求奇数的乘积

    本题是浙江理工大学ACM入队200题第八套中的E题 我们先来看一下这题的题面. 题面 输入 输入数据包含多个测试实例,每个测试实例占一行,每行的第一个数为n,表示本组数据一共有n个,接着是n个整数,你 ...

  2. 「浙江理工大学ACM入队200题系列」问题 F: 零基础学C/C++39——求方程的解

    本题是浙江理工大学ACM入队200题第四套中的F题 我们先来看一下这题的题面. 由于是比较靠前的题目,这里插一句.各位新ACMer朋友们,请一定要养成仔细耐心看题的习惯,尤其是要利用好输入和输出样例. ...

  3. 「浙江理工大学ACM入队200题系列」问题 L: 零基础学C/C++85——完美数

    本题是浙江理工大学ACM入队200题第八套中的L题 我们先来看一下这题的题面. 题面 题目描述 任何一个自然数的约数中都有1和它本身,我们把小于它本身的因数叫做这个自然数的真约数. 如6的所有真约数是 ...

  4. 「浙江理工大学ACM入队200题系列」问题 K: 零基础学C/C++84——奇偶ASCII值判断

    本题是浙江理工大学ACM入队200题第八套中的K题 我们先来看一下这题的题面. 题面 题目描述 任意输入一个字符,判断其ASCII是否是奇数,若是,输出YES,否则,输出NO; 例如,字符A的ASCI ...

  5. 「浙江理工大学ACM入队200题系列」问题 J: 零基础学C/C++83——宁宁的奥数路

    本题是浙江理工大学ACM入队200题第八套中的J题 我们先来看一下这题的题面. 题面 题目描述 宁宁参加奥数班,他遇到的第一个问题是这样的:口口口+口口口=口口口,宁宁需要将1~9 九个数分别填进对应 ...

  6. 「浙江理工大学ACM入队200题系列」问题 L: 零基础学C/C++52——计算数列和2/1,3/2,5/3,8/5......

    本题是浙江理工大学ACM入队200题第五套中的L题 我们先来看一下这题的题面. 题面 题目描述 有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13,-- 计算这个数列的前n项和.注意: ...

  7. 「浙江理工大学ACM入队200题系列」问题 A: 零基础学C/C++34—— 3个数比较大小(冒泡排序与选择排序算法)

    本题是浙江理工大学ACM入队200题第四套中的A题,同时给出了冒泡排序和选择排序算法 我们先来看一下这题的题面. 由于是比较靠前的题目,这里插一句.各位新ACMer朋友们,请一定要养成仔细耐心看题的习 ...

  8. 「浙江理工大学ACM入队200题系列」问题 H: 零基础学C/C++18——三位数反转

    本题是浙江理工大学ACM入队200题第二套中的H题 我们先来看一下这题的题面. 由于是比较靠前的题目,这里插一句.各位新ACMer朋友们,请一定要养成仔细耐心看题的习惯,尤其是要利用好输入和输出样例. ...

  9. [Python] 文科生零基础学编程系列二——数据类型、变量、常量的基础概念

    上一篇:[Python] 文科生零基础学编程系列--对象.集合.属性.方法的基本定义 下一篇: (仍先以最简单的Excel的VBA为例,语法与Python不同,但概念和逻辑需要理解透彻) p.p1 { ...

随机推荐

  1. 刷题记录:Codeforces Round #719 (Div. 3)

    Codeforces Round #719 (Div. 3) 20210703.网址:https://codeforces.com/contest/1520. 没错,我是个做div3的蒟蒻-- A 大 ...

  2. 【java】学习路线12-内部类的使用事项

    //内部类只能在其外部类当中使用//局部内部类:定义在方法里面//如果内部类和外部类有重名,就近原则在内部类中优先访问内部类.//如果想访问宿主类的同名成员,使用OuterClass.this.xxx ...

  3. 快速生成组件语法模板的插件:Auto Close Tag

    好家伙, 这是一个"标签闭合"插件 Auto Close Tag的安装: 来到VScode的拓展 安装后, 在其中输入一个左标签符号"<",随后会出现提示 ...

  4. 十一章 Kubernetes的服务发现插件--coredns

    1.前言 简单来说,服务发现就是服务(应用)之间相互定位的过程: 服务发现并非云计算时代独有的,传统的单体架构时代也会用到,以下应用场景更加需要服务发现: 服务(应用)的动态性强: 服务(应用)更新发 ...

  5. KingbaseES V8R3 shared_buffer占用过多导致实例崩溃

    背景 有这样一个案例.客户备库意外宕机,从集群日志只看出发生了主备切换,备库一直持续恢复备库没有成功,从数据库日志看到如下报错: terminating connection because of c ...

  6. Java 将Excel转为UOS

    以.uos为后缀的文件,表示Uniform Office Spreadsheet文件,是一种国产的办公文件格式,该格式以统一办公格式(UOF)创建,使用XML和压缩保存电子表格.既有的Excel表格文 ...

  7. Dapr 的 gRPC组件 (又叫可插拔组件) 的提案

    Dapr 在1.9 版本中的提案,计划在 Dapr Runtime 中组件采用 外部 gRPC 组件: https://github.com/dapr/dapr/issues/3787 ,针对这个 g ...

  8. Jmeter处理响应报文中文乱码

    Jmeter在访问发送请求的时候,响应内容如果有中文可能会显示乱码,原因应该是响应页面没有做编码处理,jmeter默认按照ISO-8859-1编码格式进行解析.而我们的响应报文却是utf-8的格式,所 ...

  9. JUC在深入面试题——三种方式实现线程等待和唤醒(wait/notify,await/signal,LockSupport的park/unpark)

    一.前言 在多线程的场景下,我们会经常使用加锁,来保证线程安全.如果锁用的不好,就会陷入死锁,我们以前可以使用Object的wait/notify来解决死锁问题.也可以使用Condition的awai ...

  10. Solutions:网站搜索 - Elastic Site Search