Skip to content

Instantly share code, notes, and snippets.

@Jackzmc
Last active June 17, 2021 17:39
Show Gist options
  • Select an option

  • Save Jackzmc/249f2a377ef23f4a4ab3dcdd33d68c9c to your computer and use it in GitHub Desktop.

Select an option

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
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