74 lines
2.6 KiB
Rust
74 lines
2.6 KiB
Rust
//! Rust rosetta example for normal distribution
|
|
use math::{histogram::Histogram, traits::ToIterator};
|
|
use rand;
|
|
use rand_distr::{Distribution, Normal};
|
|
|
|
/// Returns the mean of the provided samples
|
|
///
|
|
/// ## Arguments
|
|
/// * data -- reference to float32 array
|
|
fn mean(data: &[f32]) -> Option<f32> {
|
|
let sum: f32 = data.iter().sum();
|
|
Some(sum / data.len() as f32)
|
|
}
|
|
|
|
/// Returns standard deviation of the provided samples
|
|
///
|
|
/// ## Arguments
|
|
/// * data -- reference to float32 array
|
|
fn standard_deviation(data: &[f32]) -> Option<f32> {
|
|
let mean = mean(data).expect("invalid mean");
|
|
let sum = data.iter().fold(0.0, |acc, &x| acc + (x - mean).powi(2));
|
|
Some((sum / data.len() as f32).sqrt())
|
|
}
|
|
|
|
/// Prints a histogram in the shell
|
|
///
|
|
/// ## Arguments
|
|
/// * data -- reference to float32 array
|
|
/// * maxwidth -- the maxwidth of the histogram in # of characters
|
|
/// * bincount -- number of bins in the histogram
|
|
/// * ch -- character used to plot the graph
|
|
fn print_histogram(data: &[f32], maxwidth: usize, bincount: usize, ch: char) {
|
|
let min_val = data.iter().cloned().fold(f32::NAN, f32::min);
|
|
let max_val = data.iter().cloned().fold(f32::NAN, f32::max);
|
|
let histogram = Histogram::new(Some(&data.to_vec()), bincount, min_val, max_val).unwrap();
|
|
let max_bin_value = histogram.get_counters().iter().max().unwrap();
|
|
println!();
|
|
for x in histogram.to_iter() {
|
|
let (bin_min, bin_max, freq) = x;
|
|
let bar_width = (((freq as f64) / (*max_bin_value as f64)) * (maxwidth as f64)) as u32;
|
|
let bar_as_string = (1..bar_width).fold(String::new(), |b, _| b + &ch.to_string());
|
|
println!(
|
|
"({:>6},{:>6}) |{} {:.2}%",
|
|
format!("{:.2}", bin_min),
|
|
format!("{:.2}", bin_max),
|
|
bar_as_string,
|
|
(freq as f64) * 100.0 / (data.len() as f64)
|
|
);
|
|
}
|
|
println!();
|
|
}
|
|
|
|
/// Runs the demo to generate normal distribution of three different sample sizes
|
|
fn main() {
|
|
let expected_mean: f32 = 0.0;
|
|
let expected_std_deviation: f32 = 4.0;
|
|
let normal = Normal::new(expected_mean, expected_std_deviation).unwrap();
|
|
|
|
let mut rng = rand::thread_rng();
|
|
for &number_of_samples in &[1000, 10_000, 1_000_000] {
|
|
let data: Vec<f32> = normal
|
|
.sample_iter(&mut rng)
|
|
.take(number_of_samples)
|
|
.collect();
|
|
println!("Statistics for sample size {}:", number_of_samples);
|
|
println!("\tMean: {:?}", mean(&data).expect("invalid mean"));
|
|
println!(
|
|
"\tStandard deviation: {:?}",
|
|
standard_deviation(&data).expect("invalid standard deviation")
|
|
);
|
|
print_histogram(&data, 80, 40, '-');
|
|
}
|
|
}
|