pub fn mean(values: &[f64]) -> f64 {
if values.is_empty() {
return 0.0;
}
values.iter().sum::<f64>() / values.len() as f64
}
pub fn variance(values: &[f64]) -> f64 {
if values.len() < 2 {
return 0.0;
}
let m = mean(values);
values.iter().map(|&x| (x - m).powi(2)).sum::<f64>() / values.len() as f64
}
pub fn standard_deviation(values: &[f64]) -> f64 {
variance(values).sqrt()
}
pub fn z_score(value: f64, mean: f64, stddev: f64) -> f64 {
if stddev < 1e-10 {
return 0.0;
}
(value - mean) / stddev
}
pub fn confidence_interval(mean: f64, stddev: f64, confidence_level: f64) -> (f64, f64) {
let z_critical = if (confidence_level - 0.90).abs() < 0.01 {
1.282 } else if (confidence_level - 0.95).abs() < 0.01 {
1.645 } else if (confidence_level - 0.99).abs() < 0.01 {
2.326 } else {
1.96
};
let margin = z_critical * stddev;
(mean - margin, mean + margin)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_mean() {
let values = vec![1.0, 2.0, 3.0, 4.0, 5.0];
assert_eq!(mean(&values), 3.0);
let empty: Vec<f64> = vec![];
assert_eq!(mean(&empty), 0.0);
}
#[test]
fn test_variance() {
let values = vec![2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0];
let var = variance(&values);
assert!((var - 4.0).abs() < 0.01);
}
#[test]
fn test_standard_deviation() {
let values = vec![2.0, 4.0, 4.0, 4.0, 5.0, 5.0, 7.0, 9.0];
let std = standard_deviation(&values);
assert!((std - 2.0).abs() < 0.01);
}
#[test]
fn test_z_score() {
let z = z_score(10.0, 5.0, 2.0);
assert_eq!(z, 2.5);
let z_zero = z_score(10.0, 5.0, 0.0);
assert_eq!(z_zero, 0.0);
}
#[test]
fn test_confidence_interval() {
let (lower, upper) = confidence_interval(100.0, 10.0, 0.95);
assert!((lower - 83.55).abs() < 1.0);
assert!((upper - 116.45).abs() < 1.0);
}
}