循环结束条件要不要写超集?有什么好处?

2019-03-03 11:17:21 +08:00
 lhx2008
一直以来都是这么写循环
for (int i = 0; i < N; i++)

但是其实 i < N 是结束条件的超集,有时候如果情况比较复杂,准确写出超集似乎给写程序带来不必要的麻烦。

如果我们这样写
for (int i = 0; i != N; i++)

就准确指出了终止条件是当 i == n 时,而且 i 肯定是能到 N 的。但是甚少有人这么写,所以这背后有什么讲究呢。这两种写法各有什么优劣呢。
2337 次点击
所在节点    问与答
25 条回复
lcorange
2019-03-03 11:20:04 +08:00
比如你循环体内部用了 i 这个变量,如果有人写了错误的代码,修改了 i 的值,比如写了 i++

这样的话 i 就会在某种异常情况下比 N 大,跳过了 i == N 的情况。循环就停不下来了

但是写 i < N 可以有避免这种情况发生
lhx2008
2019-03-03 11:22:51 +08:00
@lcorange 这种情况下,i < N 就不是超集而是准确定义。
但是我们写 for 循环甚少 N 会变动的情况。那是不是应该不变的时候用 i != N 呢
lhx2008
2019-03-03 11:24:42 +08:00
@lcorange 楼上第二行我看错了。i 会加 2 这种情况,程序已经不能正常运行了,早抛出错误也好吧?
geelaw
2019-03-03 11:25:26 +08:00
我个人更喜欢 i != N,除非内部对 i 有操作。这是 STL 习惯。
geelaw
2019-03-03 11:27:51 +08:00
实际上那里是循环进行条件,而不是循环结束条件。
lcorange
2019-03-03 11:28:16 +08:00
@lhx2008 不同代码场景不一致的,比如我有个队列的数据要处理 1~100 号用户的,我写成 i<100,即使内部出错,也能保证部分用户正常使用,程序不会崩溃。但是如果我写成!=100,一旦跳过了 100 号,那服务器只能 500 报错了。

当然,你说的也没问题。在比如数值计算之类的场景,错误早就发生出现了。也就谈不上避免更大的 bug 了
lhx2008
2019-03-03 11:29:15 +08:00
@geelaw 是的哈哈,如果看成继续条件写不等于反而是超集。但是我们写代码似乎想的都是终止条件而不是继续条件
SuperMild
2019-03-03 11:33:55 +08:00
i<100 更节省脑力,不用思考 100 会不会被跳过的问题,而且也更符合逻辑,因为 i != N 的意思是不管大于还是小于 N 只要不等于 N 就应该循环,但事实上的逻辑是只有小于 N 才应该循环,等于及大于 N 都不应该循环。
hundan
2019-03-03 11:35:38 +08:00
那 i<=N 呢
SuperMild
2019-03-03 11:37:41 +08:00
另外,现在很多语言都支持 for in, for range 之类的了,有这个功能的最好尽量使用。
lhx2008
2019-03-03 11:47:01 +08:00
@SuperMild for range 我觉得是个不太好的发明,就是前后闭合的指定不清晰,python 取消标准 for 循环我觉得是个败笔。至于输入长度,有 ide 都差不多。
richard1122
2019-03-03 13:35:35 +08:00
用 < 相对于 != 是担心在循环内部有人又修改了 i 的值? 如楼上说的尽量用 for in 甚至是 arr.forEach 这类循环方式,尽量不用可变的循环变量。
另外同感 for range 不够清晰,kotlin 里面的 0..10 这种也总是记不住到底是多少。。
Leammin
2019-03-03 14:03:15 +08:00
《阿里 Java 开发手册》里边也有提到,避免使用等值来作为中断或退出条件,以免条件被"击穿",放在这里应该也是适用的。
autoxbc
2019-03-03 15:06:20 +08:00
forEach 更加函数式,只要目标有迭代器,就应该避免用 for
changnet
2019-03-03 15:12:57 +08:00
尽可能写超集,尤其是这种数字对比,又不增加什么复杂度。比如我们游戏中,策划修改了数值,不写超集程序就容易出问题

如果你的超集很复杂,这个就得看情况了
akira
2019-03-03 15:30:48 +08:00
就准确指出了终止条件是当 i == n 时,而且 i 肯定是能到 N 的。
-----------------
这个还真不好说,一旦循环体里面的代码没写好, 跳过了 N, 就死循环了
whileFalse
2019-03-03 15:34:13 +08:00
1. 习惯问题
2. N = -1,step = 2 等条件时,“<”依然适用
3. 目测大部分人都不 care 这些问题,你爱怎么写就怎么写好了
ipwx
2019-03-03 15:36:31 +08:00
@lhx2008
@richard1122 你俩这种说法,说实话就是傲慢。。。一个语言最基本的一个功能,用了这么多次,居然还说“记不住”,其实就是不想记住、看不起这俩语言的设计思路。
lhx2008
2019-03-03 15:41:57 +08:00
@ipwx 我不知道你如何得出我傲慢,JS 这么多语法糖我不信你记得清楚,比如最简单的 js 里面的 5+种遍历语法和他们的区别。

关于 range,我知道 python 里面是前闭后开,但是到别的语言里面,变成前闭后闭呢?如果我需求是前闭后闭,是不是还用得后面加一这种难看的写法?

这些不清晰,不通用的语法糖,在语言设计的时候本来就应该避免,特别是将其作为关键字的时候。
hhhsuan
2019-03-03 15:45:11 +08:00
超集用在这里合适吗

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/540504

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX