Skip to main content
Code Review

Return to Answer

replaced http://codereview.stackexchange.com/ with https://codereview.stackexchange.com/
Source Link

Instead of reading the args, converting them to Strings (which allocates memory), and then parsing them, I would probably just convert them in one pass. We can also just take the one number (thanks to Veedrac for pointing out pointing out that nth would be a better choice here):

Instead of reading the args, converting them to Strings (which allocates memory), and then parsing them, I would probably just convert them in one pass. We can also just take the one number (thanks to Veedrac for pointing out that nth would be a better choice here):

Instead of reading the args, converting them to Strings (which allocates memory), and then parsing them, I would probably just convert them in one pass. We can also just take the one number (thanks to Veedrac for pointing out that nth would be a better choice here):

added 162 characters in body
Source Link
Shepmaster
  • 8.8k
  • 27
  • 28
extern crate num;
use num::iter::range_step;
fn main() {
 let input_num =
 std::env::args()
 .skipnth(1)
 .next()
 .and_then(|x| x.parse().ok())
 .unwrap();
 let limit = usize::pow(2, input_num);
 println!("Limit: {}", limit);
 let (era_pc, era_max) = eratosthenes(limit);
 println!("Eratosthenes");
 println!("\tPrimesCounted: {}", era_pc);
 println!("\tMax prime: {}", era_max);
}
fn eratosthenes(limit: usize) -> (u64, u64) {
 let mut primes = vec![true; limit];
 primes[0] = false;
 primes[1] = false;
 let slimit = f64::sqrt(limit as f64) as usize;
 for i in 2..slimit {
 if primes[i] {
 for j in num::iter::range_step(i*i, limit, i) {
 primes[j] = false;
 }
 }
 }
 (0..limit).fold((0, 7), |(count, max), prime| {
 if primes[prime] {
 (count + 1, prime as u64)
 } else {
 (count, max)
 }
 })
}

Instead of reading the args, converting them to Strings (which allocates memory), and then parsing them, I would probably just convert them in one pass. We can also just take the one number (thanks to Veedrac for pointing out that nth would be a better choice here):

let input_num =
 std::env::args()
 .skipnth(1)
 .next()
 .and_then(|x| x.parse().ok())
 .unwrap();
extern crate num;
use num::iter::range_step;
fn main() {
 let input_num =
 std::env::args()
 .skip(1)
 .next()
 .and_then(|x| x.parse().ok())
 .unwrap();
 let limit = usize::pow(2, input_num);
 println!("Limit: {}", limit);
 let (era_pc, era_max) = eratosthenes(limit);
 println!("Eratosthenes");
 println!("\tPrimesCounted: {}", era_pc);
 println!("\tMax prime: {}", era_max);
}
fn eratosthenes(limit: usize) -> (u64, u64) {
 let mut primes = vec![true; limit];
 primes[0] = false;
 primes[1] = false;
 let slimit = f64::sqrt(limit as f64) as usize;
 for i in 2..slimit {
 if primes[i] {
 for j in num::iter::range_step(i*i, limit, i) {
 primes[j] = false;
 }
 }
 }
 (0..limit).fold((0, 7), |(count, max), prime| {
 if primes[prime] {
 (count + 1, prime as u64)
 } else {
 (count, max)
 }
 })
}

Instead of reading the args, converting them to Strings (which allocates memory), and then parsing them, I would probably just convert them in one pass. We can also just take the one number:

let input_num =
 std::env::args()
 .skip(1)
 .next()
 .and_then(|x| x.parse().ok())
 .unwrap();
extern crate num;
use num::iter::range_step;
fn main() {
 let input_num =
 std::env::args()
 .nth(1)
 .and_then(|x| x.parse().ok())
 .unwrap();
 let limit = usize::pow(2, input_num);
 println!("Limit: {}", limit);
 let (era_pc, era_max) = eratosthenes(limit);
 println!("Eratosthenes");
 println!("\tPrimesCounted: {}", era_pc);
 println!("\tMax prime: {}", era_max);
}
fn eratosthenes(limit: usize) -> (u64, u64) {
 let mut primes = vec![true; limit];
 primes[0] = false;
 primes[1] = false;
 let slimit = f64::sqrt(limit as f64) as usize;
 for i in 2..slimit {
 if primes[i] {
 for j in num::iter::range_step(i*i, limit, i) {
 primes[j] = false;
 }
 }
 }
 (0..limit).fold((0, 7), |(count, max), prime| {
 if primes[prime] {
 (count + 1, prime as u64)
 } else {
 (count, max)
 }
 })
}

Instead of reading the args, converting them to Strings (which allocates memory), and then parsing them, I would probably just convert them in one pass. We can also just take the one number (thanks to Veedrac for pointing out that nth would be a better choice here):

let input_num =
 std::env::args()
 .nth(1)
 .and_then(|x| x.parse().ok())
 .unwrap();
added 1840 characters in body
Source Link
Shepmaster
  • 8.8k
  • 27
  • 28

Benchmarking

Benchmarking is stull unstable, so you'll need to be using a nightly compiler and opt-in to the feature by adding #![feature(test)] to your crate.

You can then add something like this:

#[cfg(test)]
mod bench {
 extern crate test;
 #[bench]
 fn sieve_2(b: &mut test::Bencher) {
 b.iter(|| test::black_box(super::eratosthenes(2)))
 }
 #[bench]
 fn sieve_3(b: &mut test::Bencher) {
 b.iter(|| test::black_box(super::eratosthenes(3)))
 }
 #[bench]
 fn sieve_4(b: &mut test::Bencher) {
 b.iter(|| test::black_box(super::eratosthenes(4)))
 }
 #[bench]
 fn sieve_5(b: &mut test::Bencher) {
 b.iter(|| test::black_box(super::eratosthenes(5)))
 }
 #[bench]
 fn sieve_6(b: &mut test::Bencher) {
 b.iter(|| test::black_box(super::eratosthenes(6)))
 }
}

And run it:

$ cargo bench
running 5 tests
test bench::sieve_2 ... bench: 34 ns/iter (+/- 6)
test bench::sieve_3 ... bench: 35 ns/iter (+/- 5)
test bench::sieve_4 ... bench: 37 ns/iter (+/- 4)
test bench::sieve_5 ... bench: 40 ns/iter (+/- 21)
test bench::sieve_6 ... bench: 40 ns/iter (+/- 3)
test result: ok. 0 passed; 0 failed; 0 ignored; 5 measured

Benchmarking is done with optimizations enabled. Unfortunately, the optimizer can be too good sometimes ^_^. In this case, the optimizer completely throws away the result of your function and says that the benchmarking loop took zero time. The mysterious test::black_box function is needed in this case, as the optimizer can't see inside of it and thus can't optimize away your code.

Benchmarking

Benchmarking is stull unstable, so you'll need to be using a nightly compiler and opt-in to the feature by adding #![feature(test)] to your crate.

You can then add something like this:

#[cfg(test)]
mod bench {
 extern crate test;
 #[bench]
 fn sieve_2(b: &mut test::Bencher) {
 b.iter(|| test::black_box(super::eratosthenes(2)))
 }
 #[bench]
 fn sieve_3(b: &mut test::Bencher) {
 b.iter(|| test::black_box(super::eratosthenes(3)))
 }
 #[bench]
 fn sieve_4(b: &mut test::Bencher) {
 b.iter(|| test::black_box(super::eratosthenes(4)))
 }
 #[bench]
 fn sieve_5(b: &mut test::Bencher) {
 b.iter(|| test::black_box(super::eratosthenes(5)))
 }
 #[bench]
 fn sieve_6(b: &mut test::Bencher) {
 b.iter(|| test::black_box(super::eratosthenes(6)))
 }
}

And run it:

$ cargo bench
running 5 tests
test bench::sieve_2 ... bench: 34 ns/iter (+/- 6)
test bench::sieve_3 ... bench: 35 ns/iter (+/- 5)
test bench::sieve_4 ... bench: 37 ns/iter (+/- 4)
test bench::sieve_5 ... bench: 40 ns/iter (+/- 21)
test bench::sieve_6 ... bench: 40 ns/iter (+/- 3)
test result: ok. 0 passed; 0 failed; 0 ignored; 5 measured

Benchmarking is done with optimizations enabled. Unfortunately, the optimizer can be too good sometimes ^_^. In this case, the optimizer completely throws away the result of your function and says that the benchmarking loop took zero time. The mysterious test::black_box function is needed in this case, as the optimizer can't see inside of it and thus can't optimize away your code.

Source Link
Shepmaster
  • 8.8k
  • 27
  • 28
Loading
lang-rust

AltStyle によって変換されたページ (->オリジナル) /