use std::time::Instant; use rand::prelude::*; use std::f64::consts; use console::Term; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; fn main() { let running = Arc::new(AtomicBool::new(true)); let r = running.clone(); ctrlc::set_handler(move || { r.store(false, Ordering::SeqCst); println!(); }).expect("Error setting Ctrl-C handler"); let term = Term::stdout(); let show_progress = match std::env::var("SHOW_PROG").ok() { Some(_) => true, None => false }; let max_loops: Option = match std::env::var("LOOPS") { Ok(val) => Some(val.parse::().expect("not a valid integer")), _ => None }; match max_loops { Some(max_loops) => { println!("Running {} iterations. Press CTRL+C to exit at any time.", max_loops); run_limited(term, running, show_progress, max_loops); }, None => { println!("No maximum loops specified, running forever. Press CTRL+C to exit at any time."); run_unlimited(term, running, show_progress); } } } fn run_limited(term: Term, running: Arc, show_progress: bool, max_loops: u64) { let now = Instant::now(); let mut total_count: u64 = 0; let mut count: u64; let mut sum: f64; if show_progress { println!("Iteration\tValue \t% Err\tCurrent %\tTime Elapsed"); } for i in 0..max_loops { count = 0; sum = 0.0; while sum <= 1.0 { count += 1; sum += rand::thread_rng().gen::(); } total_count += count; if show_progress && i % 1000 == 0 { let average = total_count as f64 / i as f64; let pererror = (average - consts::E).abs() / consts::E * 100.0; let cur_percent = i as f64 / max_loops as f64 * 100.0; term.write_line(&format!(" {:9.10}\t{:.10}\t{:5.2}%\t{:9.2}%\t{:?}", i, average, pererror, cur_percent, now.elapsed())).ok(); term.move_cursor_up(1).ok(); } if !running.load(Ordering::SeqCst) { break; } } let average = total_count as f64 / max_loops as f64; let pererror = (average - consts::E).abs() / consts::E * 100.0; println!("---------------------------"); println!("Iterations: {}", max_loops); println!("Final Average: {}", average); println!("Final % Error: {:.4}%", pererror); println!("Took: {:?}", now.elapsed()); } fn run_unlimited(term: Term, running: Arc, show_progress: bool) { let now = Instant::now(); let mut total_count: u64 = 0; let mut count: u64; let mut sum: f64; let mut iteration: u64 = 0; if show_progress { println!("Iteration\tValue \t% Err\tTime Elapsed"); } loop { count = 0; sum = 0.0; while sum <= 1.0 { count += 1; sum += rand::thread_rng().gen::(); } total_count += count; if show_progress && iteration % 1000 == 0 { let average = total_count as f64 / iteration as f64; let pererror = (average - consts::E).abs() / consts::E * 100.0; term.write_line(&format!(" {:9.10}\t{:.10}\t{:5.2}%\t{:?}", iteration, average, pererror, now.elapsed())).ok(); term.move_cursor_up(1).ok(); } if !running.load(Ordering::SeqCst) { break; } iteration += 1; } let average = total_count as f64 / iteration as f64; let pererror = (average - consts::E).abs() / consts::E * 100.0; println!("---------------------------"); println!("Iterations: {}", iteration); println!("Final Average: {}", average); println!("Final % Error: {:.4}%", pererror); println!("Took: {:?}", now.elapsed()); }