numeric_statistics/f64/
variance.rs1use super::average;
2
3pub fn variance<T: AsRef<[f64]>>(values: T) -> f64 {
21 let values = values.as_ref();
22 if values.is_empty() { return f64::NAN; }
23 let average = average(values);
24 variance_with_average(values, average)
25}
26
27pub fn variance_with_average<T: AsRef<[f64]>>(values: T, average: f64) -> f64 {
47 let values = values.as_ref();
48 if values.is_empty() { return f64::NAN; }
49 let mut delta_square_sum: f64 = 0.0;
50 let mut len: usize = 0;
51 values.iter().for_each(|x|
52 if !x.is_nan() {
53 let delta = *x - average;
54 delta_square_sum += delta * delta;
55 len += 1;
56 }
57 );
58 match len {
59 0 => return f64::NAN,
60 1 => return 0.0,
61 x => delta_square_sum / (x - 1) as f64
62 }
63}
64
65#[cfg(test)]
66mod test {
67 use super::*;
68 use crate::assert_eq_f64;
69
70 #[test]
71 fn test_empty() {
72 let x: &[f64] = &[];
73 assert!(variance(x).is_nan());
74 }
75
76 #[test]
77 fn test_nan() {
78 let x: &[f64] = &[f64::NAN];
79 assert!(variance(x).is_nan());
80 }
81
82 #[test]
83 fn test_value() {
84 let x: &[f64] = &[1.0];
85 assert_eq_f64!(variance(x), 0.0);
86 }
87
88 #[test]
89 fn test_values_ascending() {
90 let x = &[1.0, 2.0, 4.0];
91 assert_eq_f64!(variance(x), 2.3333333333333333);
92 }
93
94 #[test]
95 fn test_values_ascending_and_nans() {
96 let x = &[1.0, f64::NAN, 2.0, f64::NAN, 4.0];
97 assert_eq_f64!(variance(x), 2.3333333333333333);
98 }
99
100}