while循环中的off-by-one错误到底是什么?我如何弄清楚如何解决?感谢
答案 0 :(得分:29)
例如,当您编写打算执行循环n次并编写如下内容时,off-by-one error
for (int i = 1; i < n; ++i) { ... }
或:
for (int i = 0; i <= n; ++i) { ... }
在第一种情况下,循环将执行(n - 1)次,在第二种情况下(n + 1)次,将名称逐个给出。其他变化是可能的,但通常由于循环变量的初始值或循环的结束条件中的错误,循环执行太多次或太少次。
循环可以正确编写为:
for (int i = 0; i < n; ++i) { ... }
for循环只是while循环的特例。在while循环中可以产生同样的错误。
答案 1 :(得分:2)
由于一些语言枚举从零开始的向量(例如C)和其他语言从一种开始的矢量(例如R),引起了常见的“一对一”混淆。因此,大小为x
的向量n
的成员在C中从x[0]
到x[n-1]
,但在R中从x[1]
到x[n]
。 / p>
在编码用于循环增量的惯用语时,您还面临着一对一的挑战:
在C中:
i = (i+1)%n
在R中:
i <- (i-1)%%n + 1
答案 2 :(得分:1)
假设您有以下具有数组和for
循环的代码:
char exampleArray[] = { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd' };
for(int i = 0; i <= 11; i++)
{
print(exampleArray[i])
}
在这里看到问题?因为我计算数组中有11个字符,所以将循环设置为迭代11次。但是,在大多数语言中,数组都是从零开始的,这意味着当我的代码要打印时
exampleArray[11]
我将获得一个索引超出范围的错误,因为示例中的数组在索引11处没有值。
在这种情况下,我可以通过简单地告诉我的循环重复执行一次来轻松解决此问题。
调试此问题的最简单方法是打印出上限和下限,并查看哪个值会生成超出范围的索引错误,然后将值设置为比整个迭代过程大一或小一。
当然,这是假设错误是由循环产生的,该循环超出数组的边界或比数组的边界小一个,在其他情况下,可能会发生索引越界错误,但是,这是最常见的情况。超出范围的索引将始终是指尝试访问那些由于过去的边界不在数据边界之内而没有数据的数据。
答案 3 :(得分:1)
错误一个错误 (有时称为 OBOE ) (以切片或访问段),或者在遍历它们的索引时。
如果我们将Javascript作为示例语言,则索引从零开始,而不是 one ,这意味着最后一个索引始终比的长度小1。该项目。如果您尝试访问等于长度的索引,则程序可能会抛出
“索引超出范围”参考错误
或
打印undefined
。
当您使用将索引范围作为参数的字符串或数组方法时,它有助于阅读该语言的文档并了解它们是否包含(包含给定索引的项目是返回内容的一部分)。以下是一些错误的示例:
let alphabet = "abcdefghijklmnopqrstuvwxyz";
let len = alphabet.length;
for (let i = 0; i <= len; i++) {
// loops one too many times at the end
console.log(alphabet[i]);
}
for (let j = 1; j < len; j++) {
// loops one too few times and misses the first character at index 0
console.log(alphabet[j]);
}
for (let k = 0; k < len; k++) {
// Goldilocks approves - this is just right
console.log(alphabet[k]);
}
答案 4 :(得分:0)
一个不合一的错误是当您期望某事物的价值为N时,但实际上它最终为N-1或N + 1。例如,您希望程序执行10次操作,但最终却执行9或11次(一次或多次)。在计算机科学中,最常见的情况是处理“ for”循环时发生这种情况。
由于错误判断而发生此错误,您没有意识到用来跟踪计数的数字可能与所计数的事物数不同。换句话说,您要用来计数的数字可能与您要计算的总数不同。没有什么可以使这两者相同。尝试从0到10大声计数,最后说出11个数字,但最后一个数字是10。
预防该问题的一种方法是认识到我们的大脑倾向于犯该错误(可能是认知偏见)。牢记这一点可能会帮助您识别和预防将来的情况。但是我想您可以防止(或修复)此错误的最佳方法是编写unit tests。这些测试将帮助您确保代码可以正常运行。