【发布时间】:2019-02-07 22:16:31
【问题描述】:
Rust 的 for 循环与 C 风格语言中的循环有点不同。我试图弄清楚我是否可以在 Rust 中以类似的方式获得相同的结果。 注意 i^2
for (int i = 2; i * i < n; i++)
{
// code goes here ...
}
【问题讨论】:
标签: loops syntax rust iteration
Rust 的 for 循环与 C 风格语言中的循环有点不同。我试图弄清楚我是否可以在 Rust 中以类似的方式获得相同的结果。 注意 i^2
for (int i = 2; i * i < n; i++)
{
// code goes here ...
}
【问题讨论】:
标签: loops syntax rust iteration
您始终可以对while 循环进行字面翻译。
let mut i = 2;
while i * i < n {
// code goes here
i += 1;
}
您也可以随时在无限范围内编写for 循环并在任意条件下中断:
for i in 2.. {
if i * i >= n { break }
// code goes here
}
对于这个特定的问题,您也可以使用take_while,但我不知道这是否真的比跳出 for 循环更具可读性。作为更长的“组合器”链的一部分,它会更有意义。
for i in (2..).take_while(|i| i * i < n) {
// code goes here
}
【讨论】:
来自zwol's answer 的take_while 建议是最惯用的,因此通常是最佳选择。有关循环的所有信息都保存在一个表达式中,而不是混入循环体中。
然而,最快 的实现是预先计算n 的平方根(实际上是一种奇怪的四舍五入平方根)。这样可以避免每次迭代都进行比较,因为您知道这始终是 i 的最终值。
let m = (n as f64 - 0.5).sqrt() as _;
for i in 2 ..= m {
// code goes here
}
作为旁注,我尝试对这些不同的循环进行基准测试。 take_while 是最慢的。我刚刚建议的版本总是报告0 ns/iter,我不确定这是否只是因为某些代码被优化到根本无法运行,或者它是否真的太快而无法测量。不过,对于大多数用途来说,差异并不重要。
【讨论】:
-0.5?你确定 f64 精度是安全的吗?
i 和 m。
更新:自从我写了这个答案以来,我学到了更多的 Rust。这种结构在一些罕见的情况下仍然有用(比如当循环内的逻辑需要有条件地改变计数器变量时),但通常你会想要使用像 zwol 所说的范围表达式。
我喜欢这种形式,因为它将增量保持在循环的顶部而不是底部:
let mut i = 2 - 1; // You need to subtract 1 from the initial value.
loop {
i+=1; if i*i >= n { break }
// code goes here...
}
【讨论】: