前言:其实,我每天都还好。
圣诞快乐啊各位。
虽然这篇博客的发布时间应该是25日的晚上,但博主还是在这里祝福大家在这一天与很棒的人度过了一段很棒的时光。博主的圣诞节过的也是十分的充实——吃饭睡觉当杠精,一天下来没给我累坏了。
同时也在这里祝某个圣诞节玩的很开心然后跑来跟博主"分享快乐"的靓仔开房必没身份证。
闲聊到此结束,进入正题。
正数?还是正整数?
博主在收拾行李的时候发现了一本从学长那边白嫖回来压箱底的书——《抛弃C程序设计中的谬误与恶习》。光是这个书名听起来就很吸引人,让博主我觉得此书非同小可。书中前言部分写到:
许多虔诚的学习者内心的潜意识里会以为教科书不会有什么错误,他们一向跪在教科书上学习,遇到错误时只是不断地检讨自己;
教科书同样可能有错,这种“水源”的污染才是最严重的污染;
这不比博燃?开读!
在本书的第4章中有这么一个问题:
从键盘输入一个小于1000的正数,要求输出它的平方根(若平方根不是整数,则输出其整数部分)。
要求在输入数据后先对其检查是否小于1000的正数。若不是则要求重新输入。
而书中的 样本代码(通常是一些不够完美的代码,甚至有语法错误) 是这样的:
#include <stdio.h>
#include <math.h>
#define M 1000
int main()
{
int i,k;
printf("请输入一个小于%d的整数i: ",M);
scanf("%d",&i);
while(i>M){
printf("输入的数据不符合要求,请重新输入一个小于%d的整数i: ",M);
scanf("%d",&i);
k=sqrt(i);
}
printf("%d的平方根的整数部分为%d\n",i,k);
return 0;
}
作者在对 样本代码 的解析中提到了两点:
-
k=sqrt(i);
的位置。k=sqrt(i);
所处的位置使得无论输入的i
是否符合小于1000的正数
的条件程序都会计算一次i
的平方根,十分的不合理; -
printf("请输入一个小于%d的整数i: ",M);
的表述。
按照这个表述来说,程序是允许使用者输入一个非正数的数字(比如-1
),这会使得程序存在很大的隐患;
紧接着作者给出了自己认为的对于这道题来说正确的代码:
#include <stdio.h>
#include <math.h>
#define M 1000
int main(void)
{
int n,sqrt_n=0;
int i,k;
printf("请输入一个小于%d的正整数: ",M);
while(scanf("%d",&n),n<=0||n>M)
printf("输入的数据不符合要求,请重新输入一个小于%d的整数: ",M);
int n_=n;
int odd=1;
while(n_>=odd){
n_-=odd;
sqrt_n++;
odd+=2;
}
printf("%d的平方根的整数部分为%d\n",n,sqrt_n);
return 0;
}
他的代码看似没有问题(他的求平方根的方法我很喜欢,很独特),但是仔细阅读之后会发现他的代码所解决的问题变成了:
从键盘输入一个小于1000的正整数,要求输出它的平方根(若平方根不是整数,则输出其整数部分)。
而原问题是:
从键盘输入一个小于1000的正数,要求输出它的平方根(若平方根不是整数,则输出其整数部分)。
这样来说作者的代码所解决的只是原问题的子问题,并没有完全解决原问题。更进一步讲是有曲解题意的说法。
正数分为正整数与正分数,正分数同样也是可以开方的:
1.44
=
1.2
\sqrt{1.44}=1.2
1.44
=1.2。那么想要完全解决这个问题,就需要考虑如何处理正分数。
博主想到的是用C语言的强制数据类型转换来解决,但具体还需要哪些细节,懒狗表示并没有想,因为博主很害怕涉及到浮点数的运算的。众所周知,在C语言中我们通常使用float
或double
存储一个浮点数,而这俩兄弟是会丢精度的。例如sqrt(4.0)
是有可能得到1.999999
的答案的。
不过说到这里,我就想起了那群不争气的笨蛋:这都快2022年了还有人不知道float==float
的写法是不对的吧?
在这里着重声明:
在C语言中,浮点数是无法作相等判断的。
我们通常是规定一个精度,当两个浮点数之间的差距小于这个精度时,我们可以认为它们是"相等"的。
记住了!要考的!
博主写这篇博客,并不是想表明自己比 《抛弃C程序设计中的谬误与恶习》 的作者厉害,我只是想表达出作者想要我们这些学习者所表现出的品质——不要一味的相信你所听到/看到的,对事物要怀有敬畏之心,也要保留自我的看法。
真理永远掌握在少数人手里,但你为什么觉得你不是少数人呢?
不尬吹,作者大大太厉害了,这两天翻阅下来,学到了很多东西,也发现了自己的一些错误认知。有兴趣的朋友可以看一下,很推荐的。
后话
感谢阅读,希望能对你产生一点用处。
以*词取自《银魂》第137集:
(就算是咸鱼也要有梦想啊,至少要保留着"圣诞老人会来送礼物"的梦想啊)