Last active
June 17, 2021 17:39
-
-
Save Jackzmc/249f2a377ef23f4a4ab3dcdd33d68c9c to your computer and use it in GitHub Desktop.
Calculates E using Mathematica. Use 'SHOW_PROGRESS=X' to show progress every X iteration, Set LOOPS=N to loop N times or exclude to run forever. CTRL+C will end early and report result
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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() { | |
| //Handler to terminate on CTRL+C | |
| 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(); | |
| //Parses env 'SHOW_PROGRESS', value must be an int and sets how frequent to log progress | |
| //If has a value, should log progress. | |
| let log_interval: Option<u64> = match std::env::var("SHOW_PROGRESS").ok() { | |
| Some(value) => Some(value.parse::<u64>().expect("not a valid integer")), | |
| None => None | |
| }; | |
| //Gets the maximum loops to run or none for infinity | |
| let max_loops: Option<u64> = match std::env::var("LOOPS") { | |
| Ok(val) => Some(val.parse::<u64>().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, log_interval, max_loops); | |
| }, | |
| None => { | |
| println!("No maximum loops specified, running forever. Press CTRL+C to exit at any time."); | |
| run_unlimited(term, running, log_interval); | |
| } | |
| } | |
| } | |
| //Runs upto X times | |
| fn run_limited(term: Term, running: Arc<AtomicBool>, log_interval: Option<u64>, max_loops: u64) { | |
| let now = Instant::now(); | |
| let mut total_count: u64 = 0; | |
| let mut count: u64; | |
| let mut sum: f64; | |
| //Print header only if showing progress | |
| if log_interval.is_some() { | |
| println!("Iteration\tValue \t% Err\tCurrent %\tTime Elapsed"); | |
| } | |
| for i in 0..max_loops { | |
| count = 0; | |
| sum = 0.0; | |
| //Run until sum hits 1.0 | |
| while sum <= 1.0 { | |
| count += 1; | |
| sum += rand::thread_rng().gen::<f64>(); | |
| } | |
| total_count += count; | |
| //Prints progress: | |
| if log_interval.is_some() && i % log_interval.unwrap() == 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(); | |
| } | |
| //Checks if CTRL+C was called, end loop here | |
| 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<AtomicBool>, log_interval: Option<u64>) { | |
| let now = Instant::now(); | |
| let mut total_count: u64 = 0; | |
| let mut count: u64; | |
| let mut sum: f64; | |
| let mut i: u64 = 0; | |
| if log_interval.is_some() { | |
| println!("Iteration\tValue \t% Err\tTime Elapsed"); | |
| } | |
| loop { | |
| count = 0; | |
| sum = 0.0; | |
| //Run until sum hits 1.0 | |
| while sum <= 1.0 { | |
| count += 1; | |
| sum += rand::thread_rng().gen::<f64>(); | |
| } | |
| total_count += count; | |
| //Prints progress: | |
| if log_interval.is_some() && i % log_interval.unwrap() == 0 { | |
| let average = total_count as f64 / i as f64; | |
| let pererror = (average - consts::E).abs() / consts::E * 100.0; | |
| term.write_line(&format!(" {:9.10}\t{:.10}\t{:5.2}%\t{:?}", i, average, pererror, now.elapsed())).ok(); | |
| term.move_cursor_up(1).ok(); | |
| } | |
| //Checks if CTRL+C was called, end loop here | |
| if !running.load(Ordering::SeqCst) { | |
| break; | |
| } | |
| i += 1; | |
| } | |
| let average = total_count as f64 / i as f64; | |
| let pererror = (average - consts::E).abs() / consts::E * 100.0; | |
| println!("---------------------------"); | |
| println!("Iterations: {}", i); | |
| println!("Final Average: {}", average); | |
| println!("Final % Error: {:.4}%", pererror); | |
| println!("Took: {:?}", now.elapsed()); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment