我需要实现一个for
循环,该循环从一个浮点数到另一个浮点数,步骤为另一个浮点数。
我知道如何用类似C的语言实现它:
for (float i = -1.0; i < 1.0; i += 0.01) { /* ... */ }
我还知道,在Rust中,我可以使用step_by
来指定循环步长,如果边界值和步长都是整数的话,这就给出了我想要的结果:
# ![feature(iterator_step_by)]
fn main() {
for i in (0..30).step_by(3) {
println!("Index {}", i);
}
}
当我对浮点数执行此操作时,会导致编译错误:
# ![feature(iterator_step_by)]
fn main() {
for i in (-1.0..1.0).step_by(0.01) {
println!("Index {}", i);
}
}
下面是编译输出:
error[E0599]: no method named `step_by` found for type `std::ops::Range<{float}>` in the current scope
--> src/main.rs:4:26
|
4 | for i in (-1.0..1.0).step_by(0.01) {
| ^^^^^^^
|
= note: the method `step_by` exists but the following trait bounds were not satisfied:
`std::ops::Range<{float}> : std::iter::Iterator`
`&mut std::ops::Range<{float}> : std::iter::Iterator`
如何在Rust中实现这个循环?
5条答案
按热度按时间ktca8awb1#
浮点运算的问题在于,你的代码可能会进行200次或201次迭代,这取决于循环的最后一步是
i = 0.99
还是i = 0.999999
(即使非常接近,它仍然是< 1
)。为了避免这种情况,Rust不允许在
f32
或f64
的范围内迭代,而是强制使用整数步长:另请参阅:
lvjbypge2#
作为一个真实的的迭代器:
Playground
6tqwzwtp3#
这基本上与the accepted answer中的操作相同,但您可能更喜欢这样写:
pod7payv4#
另一个答案是使用迭代器,但方式略有不同playground
在nightly下,您可以使用
conservative impl trait
功能来避免Vec
分配playgroundlnlaulya5#
由于其他人提到的原因,在大多数情况下不应该使用float进行循环。
对于那些合适的情况,它可以做到(虽然不符合人体工程学,这可能是一个很好的设计-生 rust 应该使它更难杂耍运行链锯)。
从Rust 1.34开始,
std::iter::successors()
支持直接使用浮点索引进行循环:注意有21行输出,尽管在您的问题的示例代码中,考虑到
i < 1.0
(而不是i <= 1.0
)的条件,可能只需要20行。这是由于输出中存在精度和/或累积舍入误差,即使源代码指定从-1.0迭代到1.0,增量正好为0.1。(请随意将
START
值切换为0.0或0.3,以查看不同的序列输出,* 还 * 具有精度/累积舍入误差)。Playground example