How would you write the equivalent of this C++ loop in Rust

Clash Royale CLAN TAG#URR8PPP
How would you write the equivalent of this C++ loop in Rust
Rust's for loops are a bit different than those in C-style languages. I am trying to figure out if I can achieve the same result below in a similar fashion in Rust. Note the condition where the n^2 < n.
for
for (int i = 2; i * i < n; i++)
// code goes here ...
@AbhishekRanjan: I am going to correct this.
– Midas
14 hours ago
Why would someone downvote without leaving at least a comment? That's not very helpful.
– Midas
14 hours ago
because you are not a new member and posted the question not following community standards :)
– Abhishek Ranjan
14 hours ago
@AbhishekRanjan: You at least commented on it and action was taken. I didn't get offended by that. The others just hit & run, which is worse than tagging a post incorrectly. :(
– Midas
14 hours ago
2 Answers
2
You can always do a literal translation to a while loop.
while
let mut i = 2;
while i * i < n
// code goes here
i += 1;
You can also always write a for loop over an infinite range and break out on an arbitrary condition:
for
for i in 2..
if i * i >= n break
// code goes here
For this specific problem, you could also use take_while, but I dunno if that's actually more readable than breaking out of the for loop. It would make more sense as part of a longer chain of "combinators".
take_while
for i in (2..).take_while(|i| i * i < n)
// code goes here
The take_while suggestion from zwol's answer is the most idiomatic. All of the information about the loop is kept together in a single expression instead getting mixed into the body of the loop.
take_while
However, the fastest implementation is to precompute the square root of n. This lets you avoid doing a comparison every iteration, since you know this is always the final value of i.
n
i
let m = (n as f64 - 0.5).sqrt() as _;
for i in 2 ..= m
// code goes here
As a side note, I tried to benchmark these different loops. The take_while was the slowest. The version I just suggested always reported 0 ns/iter, and I'm not sure if that's just due to some code being optimised to the point of not running at all, or if it really is too fast to measure. For most uses, the difference shouldn't be important though.
take_while
0 ns/iter
why did you put
-0.5 ? Are you sure it's safe with f64 accuracy ?– Stargateur
2 hours ago
-0.5
@Stargateur It's to ensure it always rounds down. The sqrt of a 9.0 could end up being slightly above or slightly below 3.0. At least this way, I know the answer is definitely 2.0.
– Peter Hall
5 mins ago
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
why is this tagged c++ ?
– Abhishek Ranjan
14 hours ago